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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

自动装箱,拆箱和NoSuchMethodError

發(fā)布時(shí)間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自动装箱,拆箱和NoSuchMethodError 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

J2SE 5為Java編程語(yǔ)言引入了許多功能。 這些功能之一是自動(dòng)裝箱和拆箱 ,這是我?guī)缀趺刻於紱](méi)有考慮過(guò)的功能。 它通常很方便(尤其是與收藏夾一起使用時(shí)),但有時(shí)會(huì)導(dǎo)致一些令人討厭的驚喜 ,即“ 怪異 ”和“ 瘋狂” 。 在此博客文章中,我介紹了一種罕見(jiàn)的NoSuchMethodError案例(但對(duì)我來(lái)說(shuō)很有趣),該案例是由于在自動(dòng)裝箱/拆箱之前將使用Java版本編譯的類與包含自動(dòng)裝箱/取消裝箱的Java版本編譯的類混合在一起而造成的。

下一個(gè)代碼清單顯示了一個(gè)簡(jiǎn)單的Sum類,該類可以在J2SE 5之前編寫(xiě)。它已重載了“ add”方法,這些方法接受不同的原始數(shù)值數(shù)據(jù)類型,并且Sum>每個(gè)實(shí)例Sum>簡(jiǎn)單地添加了通過(guò)以下任何一種方式提供給它的所有數(shù)字類型其重載的“添加”方法。

Sum.java(J2SE 5之前的版本)

import java.util.ArrayList;public class Sum {private double sum = 0;public void add(short newShort){sum += newShort;}public void add(int newInteger){sum += newInteger;}public void add(long newLong){sum += newLong;}public void add(float newFloat){sum += newFloat;}public void add(double newDouble){sum += newDouble;}public String toString(){return String.valueOf(sum);} }

在無(wú)法進(jìn)行拆箱之前,上述Sum類的所有客戶端都需要向這些“添加”方法提供原語(yǔ),或者,如果它們具有與原語(yǔ)相同的引用,則需要在將其中一個(gè)引用稱為“添加”方法。 在調(diào)用這些方法之前,在客戶端代碼上有責(zé)任從引用類型轉(zhuǎn)換為相應(yīng)的原始類型。 下一個(gè)代碼清單中顯示了如何完成此操作的示例。

不取消裝箱:客戶端將引用轉(zhuǎn)換為基元

private static String sumReferences(final Long longValue, final Integer intValue, final Short shortValue) {final Sum sum = new Sum();if (longValue != null){sum.add(longValue.longValue());}if (intValue != null){sum.add(intValue.intValue());}if (shortValue != null){sum.add(shortValue.shortValue());}return sum.toString(); }

J2SE 5的自動(dòng)裝箱和拆箱功能旨在解決這種情況下所需的額外工作 。 通過(guò)取消裝箱,客戶端代碼可以使用與預(yù)期的基本類型相對(duì)應(yīng)的引用類型來(lái)調(diào)用上述“添加”方法,并且這些引用將自動(dòng)“取消裝箱”為原始形式,以便可以調(diào)用適當(dāng)?shù)摹疤砑印狈椒ā?Java語(yǔ)言規(guī)范的 第5.1.8節(jié) (“取消裝箱轉(zhuǎn)換”)說(shuō)明了提供的數(shù)字引用類型在取消裝箱中將轉(zhuǎn)換為哪些原語(yǔ),該規(guī)范的 第5.1.7節(jié) (“裝箱轉(zhuǎn)換”)列出了自動(dòng)裝箱的引用類型。從自動(dòng)裝箱中的每個(gè)原語(yǔ)。

在此示例中,在調(diào)用Sum的“ add”方法之前,將引用類型轉(zhuǎn)換為對(duì)應(yīng)的原始對(duì)等類型,從而使客戶方面的拆箱工作減少了,但并沒(méi)有使客戶完全不必在提供它們之前處理數(shù)字值。 因?yàn)橐妙愋涂梢詾閚ull ,所以客戶端可以為Sum的“ add”方法之一提供null引用,并且當(dāng)Java嘗試自動(dòng)將null取消裝箱到其對(duì)應(yīng)的原語(yǔ)時(shí),將引發(fā)NullPointerException 。 下一個(gè)代碼清單從上面進(jìn)行了改編,以指示在客戶端不再需要將引用轉(zhuǎn)換為原語(yǔ),但是仍然需要檢查null以避免NullPointerException 。

自動(dòng)取消裝箱秘密對(duì)原始的引用:仍然必須檢查是否為空

private static String sumReferences(final Long longValue, final Integer intValue, final Short shortValue) {final Sum sum = new Sum();if (longValue != null){sum.add(longValue);}if (intValue != null){sum.add(intValue);}if (shortValue != null){sum.add(shortValue);}return sum.toString(); }

在設(shè)計(jì)API時(shí),可能需要避免客戶端代碼在Sum上調(diào)用“ add”方法之前檢查其引用是否為null。 消除需求的一種方法是更改??“添加”方法以顯式接受引用類型,而不是原始類型。 然后, Sum類可以在顯式或隱式(取消裝箱)對(duì)它進(jìn)行解引用之前檢查null。 接下來(lái)顯示了經(jīng)過(guò)修改的Sum類,其中包含已更改的,更易于客戶端使用的API。

用“ add”方法求和的類期望引用而不是基元

import java.util.ArrayList;public class Sum {private double sum = 0;public void add(Short newShort){if (newShort != null){sum += newShort;}}public void add(Integer newInteger){if (newInteger != null){sum += newInteger;}}public void add(Long newLong){if (newLong != null){sum += newLong;}}public void add(Float newFloat){if (newFloat != null){sum += newFloat;}}public void add(Double newDouble){if (newDouble != null){sum += newDouble;}}public String toString(){return String.valueOf(sum);} }

修改后的Sum類對(duì)客戶端更友好,因?yàn)樗试S客戶端將引用傳遞給它的任何“ add”方法,而不必?fù)?dān)心傳入的引用是否為null。 但是,如果涉及的任何一個(gè)類(客戶端類或Sum類的一個(gè)版本)都使用不同版本的Java編譯,則像這樣對(duì)Sum類的API進(jìn)行更改可能會(huì)導(dǎo)致NoSuchMethodError 。 特別是,如果客戶端代碼使用原語(yǔ)并且使用JDK 1.4或更早版本進(jìn)行編譯,并且Sum類是所示的最新版本(期望使用引用代替原語(yǔ))并且使用J2SE 5或更高版本進(jìn)行了編譯,則將遇到類似以下內(nèi)容的NoSuchMethodError (“ S”表示它是“ add”方法,它期望原始short ,而“ V”表示該方法返回void )。

Exception in thread "main" java.lang.NoSuchMethodError: Sum.add(S)Vat Main.main(Main.java:9)

另一方面,如果客戶端使用J2SE 5或更高版本進(jìn)行編譯,并且如第一個(gè)示例中那樣將原始值提供給Sum (預(yù)拆箱),并且Sum類在JDK 1.4或更早版本中使用“ add”方法進(jìn)行編譯原語(yǔ),會(huì)遇到不同版本的NoSuchMethodError 。 請(qǐng)注意,此處引用了Short參考。

Exception in thread "main" java.lang.NoSuchMethodError: Sum.add(Ljava/lang/Short;)Vat Main.main(Main.java:9)

由此可見(jiàn)對(duì)Java開(kāi)發(fā)人員的一些觀察和提醒。

  • 類路徑很重要:
    • 使用相同版本的Java(相同的-source和-target )編譯的Java .class文件可以避免本文中的特定問(wèn)題。
  • 自動(dòng)裝箱和取消裝箱的目的是很好的,并且通常非常方便,但是如果在一定程度上不牢記,可能會(huì)導(dǎo)致令人驚訝的問(wèn)題。 在這篇文章中,仍然需要檢查空值(或知道對(duì)象不是空值),這是由于拆箱而導(dǎo)致隱式解引用的情況。
  • 是否允許客戶端傳遞null并讓服務(wù)類代表它們檢查null是API風(fēng)格的問(wèn)題。 在工業(yè)應(yīng)用程序中,我將用每個(gè)方法的Javadoc注釋中的@param聲明每個(gè)“添加”方法參數(shù)是否允許為null。 在其他情況下,可能要讓調(diào)用者負(fù)責(zé)確保任何傳入的引用都不為空,并且如果調(diào)用者不遵守該約定,則拋出NullPointerException內(nèi)容將是滿意的(也應(yīng)在方法的Javadoc)。
  • 盡管通常會(huì)在完全刪除某個(gè)方法或在該方法可用之前訪問(wèn)舊類或方法的API在類型或類型數(shù)方面發(fā)生更改時(shí)看到NoSuchMethodError 。 在Java自動(dòng)裝箱和拆箱在很大程度上被視為理所當(dāng)然的日子里,很容易想到將方法從采用原語(yǔ)轉(zhuǎn)換為采用相應(yīng)的引用類型不會(huì)產(chǎn)生任何影響,但是即使這種更改也會(huì)導(dǎo)致異常,如果并非所有涉及的類都基于支持自動(dòng)裝箱和拆箱的Java版本構(gòu)建。
  • 確定要針對(duì)其編譯特定.class文件的Java版本的一種方法是使用javap -verbose并在javap輸出中查找“主要版本:”。 在本文示例中使用的類(針對(duì)JDK 1.4和Java SE 8編譯)中,“ 主要版本 ”條目分別為48和52( Java類文件上Wikipedia條目的“ 常規(guī)布局”部分列出了主要版本) )。

幸運(yùn)的是,由于構(gòu)建通常會(huì)清理所有工件并在相對(duì)連續(xù)的基礎(chǔ)上重建代碼,因此本文中使用示例和文本演示的問(wèn)題并不常見(jiàn)。 但是,在某些情況下可能會(huì)發(fā)生這種情況,最可能的情況之一是意外使用舊的JAR文件時(shí),因?yàn)樗挥谶\(yùn)行時(shí)類路徑上的等待中。

翻譯自: https://www.javacodegeeks.com/2014/08/autoboxing-unboxing-and-nosuchmethoderror.html

總結(jié)

以上是生活随笔為你收集整理的自动装箱,拆箱和NoSuchMethodError的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。