Java 8方法引用不启动线程?

Too*_*eer 2 java java-8

为什么方法引用不在此示例中启动线程?

package example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ESMethodReference {
    int i1, i2, result = 0;

    ESMethodReference(int i1, int i2){
        this.i1 =i1;
        this.i2 = i2;
    }

    public Runnable calculate(){
        System.out.print("In calculate()");
        return new Runnable() {
            @Override
            public void run() {
                result += i1 + i2;          
                System.out.print(" creating result");
            }
        };
    }

    public static void main(String[] args) throws InterruptedException{
        ESMethodReference es = new ESMethodReference(1, 1);

        ExecutorService executorService = Executors.newSingleThreadExecutor();

        for (int i = 0; i < 2; i++){
            executorService.submit(es.calculate());
            Thread.sleep(100);  // Allow new thread to run      
            System.out.println("\tes.calculate() result incremented " + es.result );

            executorService.submit(es::calculate);
            Thread.sleep(100);  // Allow new thread to run      
            System.out.println("\tes::calculate result NOT incremented " + es.result );
        }

        executorService.shutdown();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:
在calculate()中创建结果es.calculate()结果递增2
在calculate()中es :: calculate结果NOT递增2
在calculate()中创建结果es.calculate()结果递增4
在calculate()es :: calculate中结果不增加4

use*_*125 11

因为那些是不同的东西 - 传递es::calculate与传递相同:

new Runnable() {
     @Override
     public void run() {
         es.calculate();
     }
}
Run Code Online (Sandbox Code Playgroud)

显然,这与以下内容不同:

new Runnable() {
     @Override
     public void run() {
         es.calculate().run();
     }
}
Run Code Online (Sandbox Code Playgroud)

  • @VGR:你必须看[§15.12.2.5.选择最具体的方法](http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5).它表示对于显式类型的lambda表达式和精确的方法引用表达式,如果所有参数类型匹配且第二个的返回类型为"void",则功能接口类型比另一个功能接口类型更具体. (5认同)
  • @Eugene:对返回值的方法的引用仍然适用于`Runnable`,因为结果可以被删除,例如`executorService.submit((Runnable)es :: calculate);`是有效的Java代码. (4认同)
  • 实际上,我很确定es :: calculate相当于`new Callable <Runnable>(){return es.calculate(); 因为有一个返回类型,所以.即使阅读[规范](http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-),对于这种情况的确切匹配算法也不清楚. 15.13)好几次...... (3认同)

Kay*_*man 5

当你调用es.calculate()它时,返回一个Runnable代码

public void run() {
    result += i1 + i2;          
    System.out.print(" creating result");
}
Run Code Online (Sandbox Code Playgroud)

传递方法引用时es::calculate,代码运行将是

System.out.print("In calculate()");
return new Runnable() {
    @Override
    public void run() {
        result += i1 + i2;          
        System.out.print(" creating result");
    }
};
Run Code Online (Sandbox Code Playgroud)

执行方法的返回值和通过方法引用执行方法本身之间存在差异.