当Java8使用引用透明性时

时间:2014-05-23 11:17:41

标签: java java-8 referential-transparency

我们注意到java 8使用Referential Transparency

我测试了许多代码来检测此RT,例如:

public class ReferentialTransparency {
       public static int triple(int number) {
           System.out.println(number);
           try {
            Thread.sleep(500);
           } catch (Exception e) {

           }
           return number* 3;
        }
        public static void main(String[] args) {
            List<Integer> vals=Arrays.asList(1,2,3,4,3);
            System.out.println(vals.parallelStream()
                    .mapToInt(ReferentialTransparency::triple)
                    .sum());
        }
}

CONSOLE:

3
4
2
1
3
39

我注意到Java 8运行三重方法,即使有一个元素出现两次,即3

我的问题,正如Istvan所解释的那样:

  

为什么编译器没有优化重复调用三(3)   如果三重是透明的?

1 个答案:

答案 0 :(得分:8)

您的triple方法不是引用透明的,因为它既会向控制台输出内容又会休眠。这些行动都不是公开透明的。事实上,很难检测(从你的代码中)编译器是否优化了对引用透明函数的任何调用,因为如果你添加一个print语句来检测它,那么按照定义你的函数不再是引用透明。


请注意,在您提供给的链接中,给出的引用透明度的定义是

  

函数的一个属性,表达式可以被其(已评估的)值替换,而不会影响程序的含义。

您可以告诉我triple不是引用透明的,因为triple(2)不等同于6,因为仅评估6不会打印任何内容或睡眠,而triple(2)也会打印2到控制台并休眠一秒钟。由于triple(2)替换6会因删除打印和休眠而影响程序的含义,因此triple不是引用透明的。