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

前端之家收集整理的这篇文章主要介绍了在Java接口中重新定义wait方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想在一个流畅的API(用于 http://www.jooq.org)中使用wait(int)作为方法的签名.目标是能够像这个例子一样构造SQL查询
SELECT * FROM T_AUTHOR
WHERE ROWNUM <= 1
FOR UPDATE OF FIRST_NAME,LAST_NAME
WAIT 5

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

FOR UPDATE [ OF [ [ schema. ] { table | view } . ] column
             [,[ [ schema. ] { table | view } . ] column]...]
[ { NOWAIT | WAIT integer | SKIP LOCKED } ]

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();

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);

    // [...]
}

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

public class Object {
    // [...]

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

    // [...]
}

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

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

所以我的问题是:

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

解决方法

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

起初,这与继承的整个概念相矛盾 – 一旦从类继承,所有子类必须暴露相同的非私有字段&方法.您始终可以覆盖方法,除非(1)它被标记为final,(2)它具有不兼容(非协变)返回类型,这两种方法都适用于void wait(long)方法.

此外,由于每个对象都是Java中的Object,所以一切都必须有一个方法void wait(long),并且无法隐藏/删除/禁用/转发/覆盖它.假设有可能隐藏void wait(long)方法,如果你想调用它,你将如何调用它?

但是,假设您永远不需要为特定类调用void wait(long),那么AspectJ总是采用源/字节代码编织的方法,以便根据某些调用规则更改.class Java字节码.您可以捕获每个等待(长)的调用并声明错误/警告.在这里查看更多:http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-decp.html

但是,即使使用带字节码编织的AspectJ,也无法使用本机方法切入点.最有可能的是,即使使用源代码编织也无法做到这一点 – 但它可能值得一试.

猜你在找的Java相关文章