我们注意到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());
}
}
CONSOLE:
3
4
2
1
3
39
我注意到Java 8运行三重方法,即使有一个元素出现了两次,即3
。
我的问题,按照Istvan的解释,是:
为什么编译器不优化掉对triple(3)的重复调用?如果triple是引用透明的?
您的triple
方法不是引用透明的,因为它既向控制台打印内容,又休眠。这两种操作都不是引用透明的。事实上,(从代码中)检测编译器是否优化了对引用透明函数的任何调用是相当困难的,因为如果您添加了print语句来检测它,那么根据定义,您的函数不再是引用透明的。
请注意,在您提供给reference -transparency的链接中,给出的reference -transparency的定义是
函数的一种属性,在不影响程序意义的情况下,表达式可以被其(求值)替换。
你可以告诉triple
不是引用透明的,因为对triple(2)
的调用不等同于6
,因为仅仅评估6
不会打印任何东西或睡眠,而triple(2)
也会将2打印到控制台并睡眠一秒钟。由于用6
替换triple(2)
会影响程序的意义,因为它删除了打印和休眠,所以triple
不是引用透明的。