2014-05-23 52 views
2

我們注意到,Java的8使用Referential Transparency當Java8使用引用透明

我測試許多代碼來檢測這個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()); 
     } 
} 

控制檯:

3 
4 
2 
1 
3 
39 

我注意到Java 8運行三重方法,即使有一個出現兩次的元素,即3

我的問題,爲伊什特萬解釋是:

爲什麼不編譯器優化了重複調用的三倍(3) 如果三聯是引用透明?

+0

你的問題到底是什麼?我相信這可以在不使用參考透明度的情況下得到解決/回答,這會使您的問題無效。 – skiwi

+0

雖然我沒有看到問題,但問題的例子和答案的解釋都是信息性的。 – Daniel

+2

我把這個問題解釋爲「如果'triple'是引用透明的,爲什麼編譯器不會優化重複調用'triple(3)'?」 – ikdc

回答

8

您的triple方法不是引用透明的,因爲它既能打印某些內容到控制檯並睡眠。這些行爲都不具有透明性。事實上,從代碼中檢測(編譯器)是否優化了對引用透明函數的調用是非常困難的,因爲如果添加一個print語句來檢測它,那麼根據定義,您的函數不再是透明的。


注意,在你給鏈路,給定的參考透明度的定義是

函數,從而表達可通過其(評價)值代替,而不會影響的屬性程序的意義。

你可以知道triple不是透明透明的,因爲對例如triple(2)不等於6,因爲只是評估6不會打印任何東西或睡覺,而triple(2)也會打印2到控制檯並休眠一秒鐘。由於將triple(2)替換爲6將通過移除打印和睡眠來影響程序的含義,因此triple不是透明的。

+3

感謝您的詳細解釋。我希望Java對引用透明的方法有註釋,IDE會爲這類事情提供編譯器警告。 – Daniel