【发布时间】:2014-06-20 15:20:05
【问题描述】:
在 Java 8 中,我可以轻松编写:
interface Interface1 {
default void method1() {
synchronized (this) {
// Something
}
}
static void method2() {
synchronized (Interface1.class) {
// Something
}
}
}
我将获得我也可以在类中使用的完整同步语义。但是,我不能在方法声明中使用 synchronized 修饰符:
interface Interface2 {
default synchronized void method1() {
// ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
}
static synchronized void method2() {
// ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
}
}
现在,人们可以争辩说这两个接口的行为方式相同,只是Interface2 在method1() 和method2() 上建立了一个合同,这比@987654327 强一点@ 做。当然,我们也可能认为default 实现不应该对具体的实现状态做出任何假设,或者这样的关键字根本不会发挥作用。
问题:
JSR-335 专家组决定在接口方法上不支持synchronized 的原因是什么?
【问题讨论】:
-
同步是一种实现行为,它改变了编译器生成的最终字节码结果,因此可以在代码旁边使用。它在方法声明中没有意义。如果同步在抽象层上,编译器会产生什么应该会令人困惑。
-
@MartinStrejc:这可能是省略
default synchronized的解释,但不一定是static synchronized,尽管我接受后者可能已被省略一致性原因。 -
我不确定这个问题是否增加了任何价值,因为
synchronized修饰符可能会在子类中被覆盖,因此只有作为最终默认方法才有意义。 (你的另一个问题) -
@skiwi:最重要的参数是不够的。子类可以覆盖在超类中声明为
synchronized的方法,从而有效地消除同步。不过,不支持synchronized和不支持final是相关的,我不会感到惊讶,这可能是因为多重继承(例如继承void x()和synchronized void x()等)。但那是猜测。我很好奇一个权威的原因,如果有的话。 -
>>“子类可能会覆盖在超类中声明为同步的方法,从而有效地消除同步”...仅当它们不调用
super时,这需要完全重新实现和可能的访问权限给私人会员。顺便说一句,这些方法被称为“防御者”是有原因的——它们的存在是为了更容易添加新方法。
标签: java java-8 synchronized default-method jsr335