bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!

前言

這是我在抖音二面的時(shí)候自我感覺(jué)沒(méi)有答好的一題。因?yàn)槲业闹行闹皇菄@在了 TObject替換的問(wèn)題上了,并沒(méi)有去講解他會(huì)帶來(lái)的問(wèn)題。

創(chuàng)新互聯(lián)制作網(wǎng)站網(wǎng)頁(yè)找三站合一網(wǎng)站制作公司,專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站建設(shè),網(wǎng)站設(shè)計(jì),企業(yè)網(wǎng)站搭建,網(wǎng)站開(kāi)發(fā),建網(wǎng)站業(yè)務(wù),680元做網(wǎng)站,已為近1000家服務(wù),創(chuàng)新互聯(lián)網(wǎng)站建設(shè)將一如既往的為我們的客戶(hù)提供最優(yōu)質(zhì)的網(wǎng)站建設(shè)、網(wǎng)絡(luò)營(yíng)銷(xiāo)推廣服務(wù)!

思維導(dǎo)圖

抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!

什么是泛型擦除?

其實(shí)我們很常見(jiàn)這個(gè)問(wèn)題,你甚至經(jīng)常用,只是沒(méi)有去注意罷了,但是很不碰巧這樣的問(wèn)題就容易被面試官抓住。下面先來(lái)看一段代碼吧。

  List list = new ArrayList();  List listString = new ArrayList<String>();  List listInteger = new ArrayList<Integer>();

這幾段代碼簡(jiǎn)單、粗暴、又帶有很濃厚的熟悉感是吧。那我接下來(lái)要把一個(gè) 數(shù)字1插入到這三段不一樣的代碼中了。

作為讀者的你可能現(xiàn)在已經(jīng)黑人問(wèn)號(hào)了????你肯定有很多疑問(wèn),這明顯不一樣啊,怎么可能。

  public class Main {      public static void main(String[] args) {          List list = new ArrayList();          List listString = new ArrayList<String>();          List listInteger = new ArrayList<Integer>();          try {              list.getClass().getMethod("add", Object.class).invoke(list, 1);
              listString.getClass().getMethod("add", Object.class).invoke(listString, 1);              // 給不服氣的讀者們的測(cè)試之處,你可以改成字符串來(lái)嘗試。
              listInteger.getClass().getMethod("add", Object.class).invoke(listInteger, 1);
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println("list size:" + list.size());
          System.out.println("listString size:" + listString.size());
          System.out.println("listInteger size:" + listInteger.size());
      }
  }
抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!

不好意思,有圖有真相,我就是插進(jìn)去了,要是你還不信,我還真沒(méi)辦法了。

探索真相

上述的就是泛型擦除的一種表現(xiàn)了,但是為了更好的理解,當(dāng)然要更深入了是吧。雖然 List很大,但卻也不是不能看看。

兩個(gè)關(guān)鍵點(diǎn),來(lái)驗(yàn)證一下:

  1. 數(shù)據(jù)存儲(chǔ)類(lèi)型
  2. 數(shù)據(jù)獲取
  // 先來(lái)看看畫(huà)了一個(gè)大餅的List
  // 能夠過(guò)很清楚的看到泛型E
  public class ArrayList<E> extends AbstractList<E>          implements List<E>, RandomAccess, Cloneable, java.io.Serializable{       
      // 第一個(gè)關(guān)鍵點(diǎn)    
      // 還沒(méi)開(kāi)始就出問(wèn)題的存儲(chǔ)類(lèi)型
      // 難道不應(yīng)該也是一個(gè)泛型E?
      transient Object[] elementData;      public E get(int index) {
          rangeCheck(index);          return elementData(index); // 1---->
      }      // 由1直接調(diào)用的函數(shù)
      // 第二個(gè)關(guān)鍵點(diǎn),強(qiáng)制轉(zhuǎn)化得來(lái)的數(shù)據(jù)
      E elementData(int index) {          return (E) elementData[index];
      }
  }

我想,其實(shí)你也能夠懂了,這個(gè)所謂的泛型 T最后會(huì)被轉(zhuǎn)化為一個(gè) Object,最后又通過(guò)強(qiáng)制轉(zhuǎn)化來(lái)進(jìn)行一個(gè)轉(zhuǎn)變。從這里我們也就能夠知道為什么我們的數(shù)據(jù)從前面過(guò)來(lái)的時(shí)候, String類(lèi)型數(shù)據(jù)能夠直接被 Integer進(jìn)行接收了。

帶來(lái)什么樣的問(wèn)題?

(1) 強(qiáng)制類(lèi)型轉(zhuǎn)化

這個(gè)問(wèn)題的結(jié)果我們已經(jīng)在上述文章中提及到了,通過(guò)反射的方式去進(jìn)行插入的時(shí)候,我們的數(shù)據(jù)就會(huì)發(fā)生錯(cuò)誤。

如果我們?cè)谝粋€(gè) List<Integer>中在不知情的情況下插入了一個(gè) String類(lèi)型的數(shù)值,那這種重大錯(cuò)誤,我們?cè)撜艺l(shuí)去說(shuō)呢。

(2)引用傳遞問(wèn)題

上面的問(wèn)題中,我們已經(jīng)說(shuō)過(guò)了 T將在后期被轉(zhuǎn)義成 Object,那我們對(duì)引用也進(jìn)行一個(gè)轉(zhuǎn)化,是否行得通呢?

  List<String> listObject = new ArrayList<Object>();
  List<Object> listObject = new ArrayList<String>();

如果你這樣寫(xiě),在我們的檢查階段,會(huì)報(bào)錯(cuò)。但是從邏輯意義上來(lái)說(shuō),其實(shí)你真的有錯(cuò)嗎?

假設(shè)說(shuō)我們的第一種方案是正確的,那么其實(shí)就是將一堆 Object數(shù)據(jù)存入,然后再由上面所說(shuō)的強(qiáng)制轉(zhuǎn)化一般,轉(zhuǎn)化成 String類(lèi)型,聽(tīng)起來(lái)完全ok,因?yàn)樵?List中本來(lái)存儲(chǔ)數(shù)據(jù)的方式就是 Object。但其實(shí)是會(huì)出現(xiàn) ClassCastException的問(wèn)題,因?yàn)?Object是萬(wàn)物的基類(lèi),但是強(qiáng)轉(zhuǎn)是為子類(lèi)向父類(lèi)準(zhǔn)備的措施。

再來(lái)假設(shè)說(shuō)我們的第二種方案是正確的,這個(gè)時(shí)候,根據(jù)上方的數(shù)據(jù) String存入,但是有什么意義存在呢?最后都還是要成 Object的,你還不如就直接是 Object

解決方案

其實(shí)很簡(jiǎn)單,如果看過(guò)一些公開(kāi)課想來(lái)就見(jiàn)過(guò)這樣的用法。

  public class Part<T extends Parent> {      private T val;      public T getVal() {          return val;
      }      public void setVal(T val) {          this.val = val;
      }
  }

相比較于之前的 Part而言,他多了 <T extends Parent>的語(yǔ)句,其實(shí)這就是將基類(lèi)重新規(guī)劃的操作,就算被編譯,虛擬機(jī)也會(huì)知道將數(shù)據(jù)轉(zhuǎn)化為 Parent而不是直接用 Object來(lái)直接進(jìn)行替代。

應(yīng)用場(chǎng)景

這里需要感謝給我提出問(wèn)題的大佬讀者:挖掘機(jī)技術(shù)

該部分的思路來(lái)自于 Java泛型中extends和super的區(qū)別?

上面我們說(shuō)過(guò)了解決方案,使用 <T extends Parent>。其實(shí)這只是一種方案,在不同的場(chǎng)景下,我們需要加入不同的使用方法。另外官方也是提倡使用這樣的方法的,但是我們?yōu)榱吮苊馕覀兩鲜龅腻e(cuò)誤,自然需要給出一些使用場(chǎng)景了。

基于的其實(shí)是兩種場(chǎng)景,一個(gè)是擴(kuò)展型 super,一個(gè)是繼承型 extends。下面都用一個(gè)列表來(lái)舉例子。

統(tǒng)一繼承順序

  // 承載者
  class Plate<T>{      private T item;      public Plate(T t){item=t;}      public void set(T t){item=t;}      public T get(){return item;}
  }  // Lev 1
  class Food{}  // Lev 2
  class Fruit extends Food{}  class Meat extends Food{}  //Lev 3
  class Apple extends Fruit{}  class Banana extends Fruit{}  class Pork extends Meat{}  class Beef extends Meat{}  //Lev 4
  class RedApple extends Apple{}  class GreenApple extends Apple{}

<T extends Parent>

繼承型的用處是什么呢?

其實(shí)他期待的就是這整個(gè)列表的數(shù)據(jù)的基礎(chǔ)都是來(lái)自我們的 Parent,這樣獲取的數(shù)據(jù)全部人的父類(lèi)其實(shí)都是來(lái)自于我們的 Parent了,你可以叫這個(gè)列表為 Parent家族。所以也可以說(shuō)這是一個(gè)適合頻繁讀取的方案。

抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!
抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!
  Plate<? extends Fruit> p1=new Plate<Apple>(new Apple());
  Plate<? extends Fruit> p2=new Plate<Apple>(new Beef()); // 檢查不通過(guò)
  // 修改數(shù)據(jù)不通過(guò)
  p1.set(new Banana());  // 數(shù)據(jù)獲取一切正常
  // 但是他只能精確到由我們定義的Fruit
  Fruit result = p1.get();

<T super Parent>

擴(kuò)展型的作用是什么呢?

你可以把它當(dāng)成一種兼容工具,由 super修飾,說(shuō)明兼容這個(gè)類(lèi),通過(guò)這樣的方式比較適用于去存放上面所說(shuō)的 Parent列表中的數(shù)據(jù)。這是一個(gè)適合頻繁插入的方案。

抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!
抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!
  // 填寫(xiě)Food的位置,級(jí)別一定要大于或等于Fruit
  Plate<? super Fruit> p1=new Plate<Food>(new Apple());  // 和extends 不同可以進(jìn)行存儲(chǔ)
  p1.set(new Banana());  // get方法
  Banana result1 = p1.get(); // 會(huì)報(bào)錯(cuò),一定要經(jīng)過(guò)強(qiáng)制轉(zhuǎn)化,因?yàn)榉祷氐闹皇且粋€(gè)Object
  Object result2 = p1.get(); // 返回一個(gè)Object數(shù)據(jù)我們已經(jīng)屬于快要丟失掉全部數(shù)據(jù)了,所以不適合讀取

以上就是我的學(xué)習(xí)成果,如果有什么我沒(méi)有思考到的地方或是文章內(nèi)存在錯(cuò)誤,歡迎與我分享。

最后有話(huà)說(shuō)

附上我的Android核心技術(shù)學(xué)習(xí)大綱,獲取相關(guān)內(nèi)容來(lái)我的GitHub一起玩耍: https://github.com/Meng997998/AndroidJX
vx:xx1341452

對(duì)于進(jìn)階這條路而言,學(xué)習(xí)是會(huì)有回報(bào)的!

你把你的時(shí)間投資在學(xué)習(xí)上,就意味著你可以收獲技能,更有機(jī)會(huì)增加收入。

在這里分享我的Android學(xué)習(xí)PDF大全來(lái)學(xué)習(xí),這份Android學(xué)習(xí)PDF大全真的包含了方方面面了,內(nèi)含Java基礎(chǔ)知識(shí)點(diǎn)、Android基礎(chǔ)、Android進(jìn)階延伸、算法合集等等

抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!

我的這份學(xué)習(xí)合集,可以有效的幫助大家掌握知識(shí)點(diǎn)。

總之也是在這里幫助大家學(xué)習(xí)提升進(jìn)階,也節(jié)省大家在網(wǎng)上搜索資料的時(shí)間來(lái)學(xué)習(xí),也可以分享給身邊好友一起學(xué)習(xí)

獲取方式:關(guān)注我看個(gè)人介紹,或直接  點(diǎn)擊我免費(fèi)領(lǐng)取

網(wǎng)站標(biāo)題:抖音二面栽在泛型擦除?答應(yīng)我,別和我倒在同一地方!
鏈接分享:http://vcdvsql.cn/article32/pejepc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航網(wǎng)站改版搜索引擎優(yōu)化用戶(hù)體驗(yàn)品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)