java – 同步表达式中的方法引用
作者:互联网
对不起伙计们,但我无法理解,同步块内的sync()方法是同步的:
public class TestLambda {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
static void sync() throws InterruptedException {
synchronized ((Runnable)TestLambda::new) {
System.out.println("inside");
Thread.sleep(1000L);
}
}
}
如果在方法引用对象上,为什么我不能只写:
synchronized(TestLambda :: new)? (这将是编译时错误).
有任何想法吗?
UPD:以防万一:它真的是同步的
UPD-2:对于那些怀疑的人,简单的例子:
C:\sandbox\research\learn8\src>"C:\Program Files\Java\jdk1.8.0_31\bin\"javac TestLambda.java
TestLambda.java:27: error: method reference not expected here
public class Test { { synchronized (Test::new) { System.out.println("sync"); } } }
^
1 error
解决方法:
让我们看看以下2个作业:
Supplier<TestLambda> supp = TestLambda::new;
Runnable runnable = TestLambda::new;
他们两个编译得很好.基本上因为lambda或方法引用可以与多个功能接口兼容.这意味着,仅仅编写TestLambda :: new并不能告诉我们创建的对象的确切运行时类型.基于目标类型确定实例化哪个接口.并且该目标类型应始终是一个功能接口,在下面的语句中不是这种情况:
synchronized(TestLambda::new) {
}
因此,编译器不允许它,因为运行时将无法决定实例化哪个功能接口.您可以通过将方法引用强制转换为Runnable来提供该信息.所以,在下面的声明中:
synchronized((Runnable) TestLambda::new) {
}
运行时将实例化实现Runnable接口的类的对象.从某种意义上说,铸件给出了方法参考的具体性.
为了给出一个模糊的想法,这可能有点像这样翻译:
class RuntimeClass implements Runnable {
public void run() {
TestLambda testLambda = new TestLambda();
}
}
synchronized(new RuntimeClass()) {
}
P.S:RuntimeClass的实际实例将是单例(因为我们正在使用无状态方法表达式) – 我原来的错误语句
P.P.S:正如@Stuart的评论所指出的那样,无法保证对于lambda或方法引用,是否会创建新实例或返回相同的实例.所以,你不应该同步它们.
标签:method-reference,java,java-8 来源: https://codeday.me/bug/20190824/1710927.html