最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java泛型使用一些常見報(bào)錯(cuò)總結(jié)

 更新時(shí)間:2026年01月14日 11:37:16   作者:xzkyd?outpaper  
泛型是Java中一種強(qiáng)大的特性,它允許我們編寫類型安全且可重用的代碼,這篇文章主要介紹了Java泛型使用一些常見報(bào)錯(cuò)總結(jié)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

一、什么時(shí)候使用泛型會(huì)報(bào)錯(cuò)?

報(bào)錯(cuò)幾乎都發(fā)生在編譯時(shí)期,這正是泛型保護(hù)我們的地方。它們?cè)从趯?duì)泛型規(guī)則(特別是繼承規(guī)則)的誤解。

錯(cuò)誤1:誤認(rèn)為泛型類型存在繼承關(guān)系(最常見?。?/h3>

核心規(guī)則( invariance - 不可變性):

Box<String> 和 Box<Object> 沒有任何繼承關(guān)系,即使 String 是 Object 的子類。

List<String> strList = new ArrayList<>();
List<Object> objList = strList; // 編譯錯(cuò)誤! incompatible types(不兼容的類型)

為什么會(huì)報(bào)錯(cuò)?

如果編譯器允許這樣做,就會(huì)破壞類型安全。因?yàn)?nbsp;objList 的類型是 List<Object>,意味著你可以向里面添加任何 Object 的子類,比如 Integer

// 假設(shè)上面的代碼不報(bào)錯(cuò),會(huì)發(fā)生什么:
objList.add(new Integer(100)); // 這看起來是合法的,因?yàn)镮nteger是Object的子類
String firstElement = strList.get(0); // ?。。∵\(yùn)行時(shí)錯(cuò)誤:ClassCastException
// 你試圖從一個(gè)聲稱只裝String的列表里,取出一個(gè)Integer并當(dāng)成String

編譯器通過報(bào)錯(cuò)阻止了這種可能引發(fā)運(yùn)行時(shí)災(zāi)難的代碼。這就是泛型提供的編譯期類型安全

錯(cuò)誤2:試圖創(chuàng)建泛型數(shù)組

T[] array = new T[10]; // 編譯錯(cuò)誤! generic array creation(無法創(chuàng)建泛型數(shù)組)
List<String>[] listArray = new List<String>[10]; // 編譯錯(cuò)誤!

為什么會(huì)報(bào)錯(cuò)?

因?yàn)轭愋筒脸?。在運(yùn)行時(shí),T 和 String 都被擦除了,變成了 Object。JVM 無法在創(chuàng)建數(shù)組時(shí)確認(rèn) array 和 listArray 的具體類型(數(shù)組需要知道其確切的組件類型以強(qiáng)制保證類型安全)。如果允許創(chuàng)建,可能會(huì)導(dǎo)致上述的類型安全問題。

繞過方法(但不安全):

你可以創(chuàng)建一個(gè) Object[] 然后強(qiáng)制轉(zhuǎn)型,但這會(huì)收到編譯器警告,且需要自己保證類型安全。

List<String>[] listArray = (List<String>[]) new List<?>[10]; // 有警告,但不報(bào)錯(cuò)

錯(cuò)誤3:誤用通配符集合的寫入操作

List<? extends Number> numbers = new ArrayList<Integer>();
numbers.add(new Integer(100)); // 編譯錯(cuò)誤!
numbers.add(new Float(3.14f)); // 編譯錯(cuò)誤!
numbers.add(null); // 這是唯一可以的,因?yàn)閚ull沒有類型

為什么會(huì)報(bào)錯(cuò)?

List<? extends Number> 的意思是“一個(gè)只讀的列表,其元素是某種未知的、繼承自 Number 的類型”。它可能是 ArrayList<Integer>,也可能是 ArrayList<Double>。編譯器無法確定到底是哪一種,所以為了絕對(duì)的類型安全,它禁止你加入任何元素(除了 null),因?yàn)槟憧赡軙?huì)把 Double 加到 ArrayList<Integer> 里。

錯(cuò)誤4:誤用通配符集合的讀取操作

List<? super Integer> list = new ArrayList<Number>();
Integer num = list.get(0); // 編譯錯(cuò)誤!
Number num2 = list.get(0); // 編譯錯(cuò)誤!
Object obj = list.get(0); // 這是唯一可以的

為什么會(huì)報(bào)錯(cuò)?

List<? super Integer> 的意思是“一個(gè)只寫的列表,其元素是某種未知的、Integer 的父類型”。你從里面取出的元素,編譯器只能確定它是 Integer 的某個(gè)父類,但無法確定具體是 Number 還是 Object。因此,為了保證安全,它只允許你賦值給最頂層的 Object 引用。

二、泛型“繼承”關(guān)系的正確認(rèn)知

如何理解這張圖:

  1. 不變性 (Invariance - 紅色部分):這是最根本的規(guī)則。List<String> 和 List<Object> 在類型系統(tǒng)上是完全不同的類型,沒有繼承關(guān)系。你不能將它們互相賦值。試圖這么做是絕大多數(shù)編譯錯(cuò)誤的根源。

  2. 協(xié)變 (Covariance - 通過 ? extends 實(shí)現(xiàn),綠色部分):雖然 List<Integer> 不是 List<Number> 的子類,但你可以通過上界通配符 List<? extends Number> 來獲得一個(gè)“只讀”的、安全的“繼承”視圖。一個(gè) ArrayList<Integer> 可以被當(dāng)作一個(gè) List<? extends Number> 來使用。這模擬了協(xié)變(子類容器可以被視為父類容器)。

  3. 逆變 (Contravariance - 通過 ? super 實(shí)現(xiàn),綠色部分):同樣,你可以通過下界通配符 List<? super Integer> 來獲得一個(gè)“只寫”的、安全的“繼承”視圖。一個(gè) ArrayList<Number> 甚至 ArrayList<Object> 都可以被當(dāng)作一個(gè) List<? super Integer> 來使用。這模擬了逆變(父類容器可以被視為子類容器,但用途相反)。

記住:

  • <T>: 用于當(dāng)你既需要“讀”也需要“寫”操作時(shí)。這是最常用、最直接的方式。

  • <? extends T>: 只讀。當(dāng)你只需要從集合中獲取元素時(shí)使用(Producer)。

  • <? super T>: 只寫。當(dāng)你只需要向集合中添加元素時(shí)使用(Consumer)。

三、常見問題總結(jié)

Q:“談?wù)凧ava泛型中使用不當(dāng)會(huì)導(dǎo)致的問題和泛型的繼承關(guān)系。”

A:

“使用泛型最容易出錯(cuò)的地方是對(duì)泛型容器繼承關(guān)系的誤解。核心規(guī)則是泛型具有不變性Container<SubClass> 和 Container<SuperClass> 沒有繼承關(guān)系,即使 SubClass 繼承自 SuperClass。試圖將它們相互賦值是主要的編譯錯(cuò)誤來源。

之所以這樣設(shè)計(jì),是為了保證絕對(duì)的編譯期類型安全。如果允許這種賦值,就可以把 SuperClass 對(duì)象放入一個(gè)聲明為只裝 SubClass 的容器中,從而在后續(xù)讀取時(shí)引發(fā)運(yùn)行時(shí) ClassCastException。

為了在需要時(shí)實(shí)現(xiàn)類似繼承的靈活性,Java引入了通配符:

  • <? extends T> 實(shí)現(xiàn)了協(xié)變,讓我們能安全地讀取元素,將容器視為元素的生產(chǎn)者。

  • <? super T> 實(shí)現(xiàn)了逆變,讓我們能安全地寫入元素,將容器視為元素的消費(fèi)者。

其他常見錯(cuò)誤還包括試圖創(chuàng)建泛型數(shù)組或?qū)嵗愋蛥?shù),這些都源于泛型在運(yùn)行時(shí)類型信息被擦除的實(shí)現(xiàn)機(jī)制。

PECS(Producer-Extends, Consumer-Super) 原則是指導(dǎo)我們正確使用通配符、避免編譯錯(cuò)誤的最佳實(shí)踐。理解了不變性是基礎(chǔ),協(xié)變和逆變是工具,就能絕大多數(shù)泛型相關(guān)的編譯錯(cuò)誤。

到此這篇關(guān)于Java泛型使用一些常見報(bào)錯(cuò)總結(jié)的文章就介紹到這了,更多相關(guān)Java泛型使用報(bào)錯(cuò)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

萨嘎县| 鲁山县| 大余县| 海安县| 昔阳县| 甘泉县| 习水县| 漯河市| 西乌| 安顺市| 昌图县| 周至县| 永和县| 内江市| 吴旗县| 搜索| 新建县| 淮安市| 静海县| 林西县| 淳安县| 山东| 开阳县| 仙居县| 民县| 永州市| 龙山县| 渝中区| 大埔区| 新田县| 迁西县| 临高县| 镶黄旗| 自贡市| 鄂托克前旗| 道孚县| 若尔盖县| 宽城| 稻城县| 富阳市| 墨江|