java - 同步表达式中的方法引用

标签 java java-8 method-reference

对不起大家,但我不明白,sync() 方法内的哪个对象是 synchronized block 是同步的:

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

如果在方法引用对象上,为什么我不能只写: 同步 (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 或方法引用可以与多个功能接口(interface)兼容。这意味着,仅编写 TestLambda::new 并不能告诉我们所创建对象的确切运行时类型。要实例化哪个接口(interface)是根据目标类型确定的。并且该目标类型应始终是功能接口(interface),但在以下语句中不是这种情况:

synchronized(TestLambda::new) {
}

因此,编译器不允许这样做,因为运行时无法决定实例化哪个功能接口(interface)。您可以通过将方法引用强制转换为 Runnable 来提供该信息。所以,在下面的声明中:

synchronized((Runnable) TestLambda::new) {
}

运行时将实例化实现Runnable 接口(interface)的类的对象。从某种意义上说,转换为方法引用提供了具体性。

为了给出一个模糊的想法,这在某种程度上可以这样翻译:

class RuntimeClass implements Runnable {
    public void run() {
        TestLambda testLambda = new TestLambda();
    }
}

synchronized(new RuntimeClass()) {
}

P.S:RuntimeClass 的实际实例将是单例的(因为我们使用的是无状态方法表达式)——我原来的错误陈述

P.P.S:正如@Stuart 的评论所述,无法保证对于 lambda 或方法引用,是否会创建新实例或返回相同的实例。所以,你不应该同步它们。

关于java - 同步表达式中的方法引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29439136/

相关文章:

java - 目录选择画面、初始目录、无人值守模式下的标准目录

java - 在并行流中遇到空对象时添加日志

java - Java中的List如何实现静态对非静态的引用?

java - 如何解决来自 LambdaMetafactory 的不正确参数

Java 创建 Iterable<?从 Iterator<SubClass> 扩展 SuperClass> 而不发出警告

java - 如何使用内存映射文件在两个 JVM 之间进行通信?

java - 使用 Spring Mvc 的 REST 请求上的 HTTP 400 错误请求

java - 将分区扩展至多一级

testing - Java 8 Lambda 的单元测试

java - Comparator.reversed() 不使用 lambda 编译