在Java接口中重新定义wait方法

Luk*_*der 6 java sql api-design overloading object

我想wait(int)在流畅的API(用于http://www.jooq.org)中使用方法的签名.目标是能够像这个例子一样构造SQL查询:

SELECT * FROM T_AUTHOR
WHERE ROWNUM <= 1
FOR UPDATE OF FIRST_NAME, LAST_NAME
WAIT 5
Run Code Online (Sandbox Code Playgroud)

完整的FOR UPDATE子句语法规范(至少对于Oracle)可以在这里看到:

FOR UPDATE [ OF [ [ schema. ] { table | view } . ] column
             [, [ [ schema. ] { table | view } . ] column]...]
[ { NOWAIT | WAIT integer | SKIP LOCKED } ]
Run Code Online (Sandbox Code Playgroud)

http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/img_text/for_update_clause.htm

使用jOOQ,我真的希望接近SQL语法.所以我希望能够使用jOOQ流畅的API对上面的SQL子句进行建模,如下所示:

Result<Record> result = create.select()
                              .from(T_AUTHOR)
                              .limit(1)
                              .forUpdate()
                              .of(FIRST_NAME, LAST_NAME)
                              .wait(5) // Here's the issue
                              .fetch();
Run Code Online (Sandbox Code Playgroud)

fetch方法用于将API的底层对象呈现为SQL,并针对Oracle(或任何其他)数据库运行SQL语句.以上内容可以在界面中合法指定:

/**
 * A type that models a "step" in the creation of a query using the fluent API
 */
public interface SelectForUpdateWaitStep extends SelectFinalStep {
    // [...]

    /**
     * Add a "FOR UPDATE .. WAIT n" clause to the query
     */
    SelectFinalStep wait(int seconds);

    // [...]
}
Run Code Online (Sandbox Code Playgroud)

不过,我对此有一些疑问,因为存在与另一种方法发生冲突的风险:

public class Object {
    // [...]

    public final native void wait(long timeout) throws InterruptedException;

    // [...]
}
Run Code Online (Sandbox Code Playgroud)

感谢方法重载(intlong参数相比),我实际上可以做到这一点.但我担心它可能会让我的用户感到困惑并导致错误.所以这是错的:

                              .forUpdate()
                              .of(FIRST_NAME, LAST_NAME)
                              .wait((long) 5) // This doesn't make sense
                              .fetch();       // This doesn't compile
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  1. 我可以以某种方式阻止呼叫/访问Object.wait(long)altoghether?我不这么认为,因为它已经宣布,final但也许有人知道编译器技巧,或其他什么?
  2. 除了将方法重命名为愚蠢doWait(int)或类似的东西之外,您对我的API设计有更好的想法WAIT(int)吗?

Nic*_*ick 2

这需要一种禁用Object方法的方法。主要原因似乎是因为它有一个很好的名称,适合专有 API 的用途。

首先,这与继承的整个概念相矛盾——一旦从一个类继承,所有子类都必须公开相同的非私有字段和方法。您始终可以重写方法,除非 (1) 它被标记为final并且 (2) 它具有不兼容(非协变)的返回类型,这两种情况对于该void wait(long)方法都是正确的。

此外,由于ObjectJava 中的每个对象都是一个对象,因此所有对象都必须有一个方法void wait(long),并且不应该有任何方法来隐藏/删除/禁用/转发/覆盖它。假设可以隐藏该void wait(long)方法,您将如何调用它,您是否希望调用它?

然而,假设您永远不需要调用特定的类, AspectJvoid wait(long)总是使用源/字节码编织方法,以便根据某些调用规则对 .class Java 字节码进行更改。您可以捕获每次调用并声明错误/警告。在此处查看更多信息:http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-decp.htmlwait(long)

然而,即使使用具有字节码编织的 AspectJ,本机方法切入点也是不可能的。即使使用源代码编织,这很可能也是不可能的——但可能值得一试。

  • 是的,这就像重写编译器......;-) (2认同)
  • 我自己不太确定我是否喜欢这个想法还是应该讨厌它。但这绝对是非常有趣的。 (2认同)