日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 8的方法参考进一步限制了重载

發布時間:2023/12/3 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 8的方法参考进一步限制了重载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

方法重載一直是一個充滿喜憂參半的話題。 我們已經在博客上介紹了它,并介紹了幾次警告:

  • 您會后悔對Lambdas應用重載!
  • 保持干燥:方法重載
  • 為什么每個人都討厭操作員超載
  • API設計師,請小心

重載有用的主要原因有兩個:

  • 允許使用默認參數
  • 允許分離的參數類型替代
  • Bot原因僅僅是出于為API使用者提供便利的目的。 在JDK中很容易找到很好的例子:

    默認參數

    public class Integer {public static int parseInt(String s) {return parseInt(s,10);}public static int parseInt(String s, int radix) {} }

    在上面的示例中,第一個parseInt()方法只是使用最常用的基數調用第二個方法的一種簡便方法。

    析取參數類型替代

    有時,使用不同類型的參數可以實現相似的行為,這意味著相似的事物,但在Java的類型系統中不兼容。 例如,當構造一個String :

    public class String {public static String valueOf(char c) {char data[] = {c};return new String(data, true);}public static String valueOf(boolean b) {return b ? "true" : "false";}// and many more... }

    如您所見,根據參數類型優化了相同方法的行為。 由于兩個valueOf()方法的語義相同,因此在讀寫源代碼時這不會影響該方法的“感覺”。

    此技術的另一個用例是常用時,相似但不兼容的類型需要在彼此之間方便地轉換。 作為API設計人員,您不想讓這樣繁瑣的轉換使您的API消費者感到無聊。 相反,您提供:

    public class IOUtils {public static void copy(InputStream input, OutputStream output);public static void copy(InputStream input, Writer output);public static void copy(InputStream input, Writer output, String encoding);public static void copy(InputStream input, Writer output, Charset encoding); }

    這是一個很好的示例,它同時顯示了默認參數(可選編碼)以及參數類型替代項( OutputStream與Writer或String與Charset編碼表示形式)。

    邊注

    我懷疑聯合類型和默認參數船很早以前就已經為Java航行了-盡管聯合類型可能被實現為語法糖,但是默認參數將是引入JVM的野獸,因為它將取決于JVM對Java的缺少支持。命名參數。

    正如Ceylon語言所顯示的那樣,這兩個功能覆蓋了所有方法重載用例的99%,這就是為什么Ceylon可以在不重載的情況下完全完成-在JVM之上!

    超載是危險且不必要的

    上面的示例表明,重載實質上只是幫助人們與API交互的一種手段。 對于運行時,沒有重載之類的東西。 調用僅以字節碼“靜態”鏈接到不同的,唯一的方法簽名(給出或采用更新的操作碼,例如invokedynamic)。 但是要點是,對于上述計算機,如果上述方法全部都稱為copy() ,或者被明確地調用了m1() , m2() , m3()和m4() ,則對計算機沒有區別。

    另一方面,重載在Java源代碼中是真實的,并且編譯器必須做大量工作才能找到最具體的方法,否則將應用JLS的復雜重載解析算法。 每個新的Java語言版本都會使情況變得更糟。 例如,在Java 8中,方法引用將給API使用者帶來更多痛苦,并且需要API設計人員的額外照顧。 考慮一下Josh Bloch的以下示例:

    //發現bug靜態void pfc(List <Integer> x){x.stream()。map(Integer :: toString).forEach(s-> System.out.println(s.charAt(0))); }

    — Joshua Bloch(@joshbloch) 2015年7月20日

    您可以將上面的代碼復制粘貼到Eclipse中,以驗證編譯錯誤(請注意,最新的編譯器可能會報告類型推斷副作用,而不是實際錯誤)。 Eclipse為以下簡化報告了編譯錯誤:

    static void pfc(List<Integer> x) {Stream<?> s = x.stream().map(Integer::toString); }

    …是

    Ambiguous method reference: both toString() and toString(int) from the type Integer are eligible

    糟糕!

    上面的表達是模棱兩可的。 它可以表示以下兩個表達式之一:

    // Instance method: x.stream().map(i -> i.toString());// Static method: x.stream().map(i -> Integer.toString(i));

    可以看出,使用lambda表達式而不是方法引用可以立即解決歧義。 解決此歧義(朝向實例方法)的另一種方法是改用toString()的超類型聲明,該聲明不再模糊不清:

    // Instance method: x.stream().map(Object::toString);

    結論

    API設計者的結論非常清楚:

    自Java 8以來,方法重載已成為API設計人員更加危險的工具。

    盡管上述內容并非真正“嚴峻”,但當API使用者的編譯器拒絕看似正確的代碼時,他們將花費大量時間來克服這種認知上的摩擦。 從該示例中獲取的一個大人造假菜是:

    切勿混合使用類似的實例和靜態方法重載

    實際上,這會放大您的靜態方法重載何時重載java.lang.Object的名稱, 正如我們在先前的博客文章中所解釋的那樣 。

    遵循以上規則很簡單。 因為只有兩個有效的重載原因(默認參數和不兼容的參數替代),所以沒有必要為同一類中的方法提供靜態重載。 一個更好的設計(如JDK所公開)是具有“伴侶類”的,類似于Scala的伴侶對象。 例如:

    // Instance logic public interface Collection<E> {} public class Object {}// Utilities public class Collections {} public final class Objects {}

    通過更改方法的名稱空間,可以在某種程度上很好地規避重載,并且不會出現以前的問題。

    TL; DR:避免超載,除非增加的便利性真正增加了價值!

    翻譯自: https://www.javacodegeeks.com/2015/08/java-8s-method-references-put-further-restrictions-on-overloading.html

    總結

    以上是生活随笔為你收集整理的Java 8的方法参考进一步限制了重载的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。