当Java8使用引用透明性时

Abd*_*UMI 2 java referential-transparency java-8

我们注意到java 8使用了参考透明度 :

我测试了很多代码来检测这个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());
        }
}
Run Code Online (Sandbox Code Playgroud)

安慰 :

3
4
2
1
3
39
Run Code Online (Sandbox Code Playgroud)

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

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

如果三重引用透明,为什么编译器不会优化重复调用三元组(3)?

Lil*_*ung 8

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


请注意,在您给予的链接中,给出的的定义是

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

你可以triple说它不是引用透明的,因为对eg的调用triple(2)不等同6,因为只是评估6不会打印任何内容或睡眠,同时triple(2)还会打印2到控制台并睡一秒钟.由于替换triple(2)通过6将通过移除印刷和睡眠影响程序的意思,triple不是引用透明.

  • 谢谢你的彻底解释.我希望Java有关于引用透明方法的注释,IDE会为这种事情提供编译器警告. (3认同)