日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Java泛型需要注意的問題

 我們都知道Java 在 1.5 引入了泛型機制,泛型的本質(zhì)是參數(shù)化類型,也就是說變量的類型是一個參數(shù),在使用時再指定為具體類型。泛型可以用于類、接口、方法,通過使用泛型可以使代碼更簡單、安全。本文通過參考《Java編程思想》對泛型使用過程中需要注意的問題進行了總結(jié)以及給大家提供一些泛型相關(guān)的面試題供大家學(xué)習(xí)使用。

成都創(chuàng)新互聯(lián)公司是專業(yè)的麻章網(wǎng)站建設(shè)公司,麻章接單;提供網(wǎng)站設(shè)計、成都網(wǎng)站設(shè)計,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進行麻章網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!

泛型相關(guān)問題

1、泛型類型引用傳遞問題

在 Java 中,像下面形式的引用傳遞是不允許的:

 
 
 
  1. ArrayList arrayList1=new ArrayList();//編譯錯誤
  2. ArrayList arrayList1=new ArrayList();//編譯錯誤

    我們先看第一種情況,將第一種情況拓展成下面的形式:

     
     
     
    1. ArrayList arrayList1=new ArrayList();
    2. arrayList1.add(new Object());
    3. arrayList1.add(new Object());
    4. ArrayList arrayList2=arrayList1;//編譯錯誤
    5. 實際上,在第 4 行代碼處,就會有編譯錯誤。那么,我們先假設(shè)它編譯沒錯。那么當(dāng)我們使用arrayList2 引用用 get()方法取值的時候,返回的都是 String 類型的對象,可是它里面實際上已經(jīng)被我們存放了 Object 類型的對象,這樣,就會有 ClassCastException 了。所以為了避免這種極易出現(xiàn)的錯誤,Java 不允許進行這樣的引用傳遞。(這也是泛型出現(xiàn)的原因,就是為了解決類型轉(zhuǎn)換的問題,我們不能違背它的初衷)。

      在看第二種情況,將第二種情況拓展成下面的形式:

       
       
       
      1. ArrayList arrayList1=new ArrayList();
      2. arrayList1.add(new String());
      3. arrayList1.add(new String());
      4. ArrayList arrayList2=arrayList1;//編譯錯誤

        沒錯,這樣的情況比第一種情況好的多,最起碼,在我們用 arrayList2 取值的時候不會出現(xiàn)ClassCastException,因為是從 String 轉(zhuǎn)換為 Object??墒?,這樣做有什么意義呢,泛型出現(xiàn)的原因,就是為了解決類型轉(zhuǎn)換的問題。我們使用了泛型,到頭來,還是要自己強轉(zhuǎn),違背了泛型設(shè)計的初衷。所以 java 不允許這么干。再說,你如果又用 arrayList2 往里面 add()新的對象,那么到時候取得時候,我怎么知道我取出來的到底是 String 類型的,還是 Object 類型的呢?所以,要格外注意泛型中引用傳遞問題。

        2、泛型類型變量不能是基本數(shù)據(jù)類型

        就比如,沒有 ArrayList,只有 ArrayList。因為當(dāng)類型擦除后,ArrayList 的原始類中的類型變量(T)替換為 Object,但 Object 類型不能存儲 double 值。

        3、運行時類型查詢

         
         
         
        1. ArrayList arrayList=new ArrayList();if( arrayList instanceof ArrayLi

        因為類型擦除之后,ArrayList只剩下原始類型,泛型信息 String 不存在了。

        4、泛型在靜態(tài)方法和靜態(tài)類中的問題

        泛型類中的靜態(tài)方法和靜態(tài)變量不可以使用泛型類所聲明的泛型類型參數(shù)

         
         
         
        1. public class Test2 {
        2. public static T one; //編譯錯誤
        3. public static T show(T one){ //編譯錯誤
        4. return null;
        5. } }

        因為泛型類中的泛型參數(shù)的實例化是在定義泛型類型對象(例如 ArrayList)的時候指定的,而靜態(tài)變量和靜態(tài)方法不需要使用對象來調(diào)用。對象都沒有創(chuàng)建,如何確定這個泛型參數(shù)是何種類型,所以當(dāng)然是錯誤的。

        但是要注意區(qū)分下面的一種情況:

         
         
         
        1. public class Test2 {
        2. public static T show(T one){//這是正確的
        3. return null;
        4. } }

        因為這是一個泛型方法,在泛型方法中使用的 T 是自己在方法中定義的 T,而不是泛型類中的 T。

        泛型相關(guān)面試題

        1. Java 中的泛型是什么 ? 使用泛型的好處是什么?

        泛型是一種參數(shù)化類型的機制。它可以使得代碼適用于各種類型,從而編寫更加通用的代碼,例如集合框架。泛型是一種編譯時類型確認機制。它提供了編譯期的類型安全,確保在泛型類型(通常為泛型集合)上只能使用正確類型的對象,避免了在運行時出現(xiàn) ClassCastException。

        2、Java 的泛型是如何工作的 ? 什么是類型擦除 ?

        泛型的正常工作是依賴編譯器在編譯源碼的時候,先進行類型檢查,然后進行類型擦除并且在類型參數(shù)出現(xiàn)的地方插入強制轉(zhuǎn)換的相關(guān)指令實現(xiàn)的。

        編譯器在編譯時擦除了所有類型相關(guān)的信息,所以在運行時不存在任何類型相關(guān)的信息。例如List在運行時僅用一個 List 類型來表示。為什么要進行擦除呢?這是為了避免類型膨脹。

        3. 什么是泛型中的限定通配符和非限定通配符 ?

        限定通配符對類型進行了限制。有兩種限定通配符,一種是它通過確保類型必須是 T 的子類來設(shè)定類型的上界,另一種是它通過確保類型必須是 T 的父類來設(shè)定類型的下界。泛型類型必須用限定內(nèi)的類型來進行初始化,否則會導(dǎo)致編譯錯誤。另一方面表示了非限定通配符,因為可以用任意類型來替代。

        4. List和 List 之間有什么區(qū)別 ?

        這和上一個面試題有聯(lián)系,有時面試官會用這個問題來評估你對泛型的理解,而不是直接問你什么是限定通配符和非限定通配符。這兩個 List 的聲明都是限定通配符的例子,List可以接受任何繼承自 T 的類型的 List,而 List可以接受任何 T 的父類構(gòu)成的 List。例如 List可以接受 List或 List。在本段出現(xiàn)的連接中可以找到更多信息。

        5. 如何編寫一個泛型方法,讓它能接受泛型參數(shù)并返回泛型類型?

        編寫泛型方法并不困難,你需要用泛型類型來替代原始類型,比如使用 T, E or K,V 等被廣泛認可的類型占位符。泛型方法的例子請參閱 Java 集合類框架。最簡單的情況下,一個泛型方法可能會像這樣:

         
         
         
        1. public V put(K key, V value) {
        2. return cache.put(key, value);
        3. }

        6. Java 中如何使用泛型編寫帶有參數(shù)的類?

        這是上一道面試題的延伸。面試官可能會要求你用泛型編寫一個類型安全的類,而不是編寫一個泛型方法。關(guān)鍵仍然是使用泛型類型來代替原始類型,而且要使用 JDK 中采用的標(biāo)準占位符。

        7. 編寫一段泛型程序來實現(xiàn) LRU 緩存?

        對于喜歡 Java 編程的人來說這相當(dāng)于是一次練習(xí)。給你個提示,LinkedHashMap 可以用來實現(xiàn)固定大小的 LRU 緩存,當(dāng) LRU 緩存已經(jīng)滿了的時候,它會把最老的鍵值對移出緩存。LinkedHashMap 提供了一個稱為 removeEldestEntry()的方法,該方法會被 put()和 putAll()調(diào)用來刪除最老的鍵值對。

        8. 你可以把 List傳遞給一個接受 List參數(shù)的方法嗎?(見上面說明)

        對任何一個不太熟悉泛型的人來說,這個 Java 泛型題目看起來令人疑惑,因為乍看起來 String 是一種Object,所以 List應(yīng)當(dāng)可以用在需要 List的地方,但是事實并非如此。真這樣做的話會導(dǎo)致編譯錯誤。如果你再深一步考慮,你會發(fā)現(xiàn) Java 這樣做是有意義的,因為 List可以存儲任何類型的對象包括 String, Integer 等等,而 List卻只能用來存儲 Strings。

        9. Array 中可以用泛型嗎?

        這可能是 Java 泛型面試題中最簡單的一個了,當(dāng)然前提是你要知道 Array 事實上并不支持泛型,這也是為什么 Joshua Bloch 在 Effective Java 一書中建議使用 List 來代替 Array,因為 List 可以提供編譯期的類型安全保證,而 Array 卻不能。

        10. 如何阻止 Java 中的類型未檢查的警告?

        如果你把泛型和原始類型混合起來使用,例如下列代碼,Java 5 的 javac 編譯器會產(chǎn)生類型未檢查的警告,例如 List rawList = new ArrayList()注意: Hello.java 使用了未檢查或稱為不安全的操作;這種警告可以使用@SuppressWarnings("unchecked")注解來屏蔽。

        11、Java 中 List和原始類型 List 之間的區(qū)別?

        原始類型和帶參數(shù)類型之間的主要區(qū)別是,在編譯時編譯器不會對原始類型進行類型安全檢查,卻會對帶參數(shù)的類型進行檢查,通過使用 Object 作為類型,可以告知編譯器該方法可以接受任何類型的對象,比如 String 或 Integer。這道題的考察點在于對泛型中原始類型的正確理解。它們之間的第二點區(qū)別是,你可以把任何帶參數(shù)的泛型類型傳遞給接受原始類型 List 的方法,但卻不能把List傳遞給接受 List的方法,因為會產(chǎn)生編譯錯誤。

        12、Java 中 List和 List之間的區(qū)別是什么?

        這道題跟上一道題看起來很像,實質(zhì)上卻完全不同。List 是一個未知類型的 List,而List其實是任意類型的 List。你可以把 List, List賦值給 List,卻不能把 List賦值給 List。

         
         
         
        1. List listOfAnyType;
        2. List listOfObject = new ArrayList();
        3. List listOfString = new ArrayList();
        4. List listOfInteger = new ArrayList();
        5. listOfAnyType = listOfString; //legal
        6. listOfAnyType = listOfInteger; //legal
        7. listOfObjectType = (List) listOfString; //compiler error - in-convertible ty

          13、List和原始類型 List 之間的區(qū)別.

          該題類似于“原始類型和帶參數(shù)類型之間有什么區(qū)別”。帶參數(shù)類型是類型安全的,而且其類型安全是由編譯器保證的,但原始類型 List 卻不是類型安全的。你不能把 String 之外的任何其它類型的 Object 存入String 類型的 List 中,而你可以把任何類型的對象存入原始 List 中。使用泛型的帶參數(shù)類型你不需要進行類型轉(zhuǎn)換,但是對于原始類型,你則需要進行顯式的類型轉(zhuǎn)換。

           
           
           
          1. List listOfRawTypes = new ArrayList();
          2. listOfRawTypes.add("abc");
          3. listOfRawTypes.add(123); //編譯器允許這樣 - 運行時卻會出現(xiàn)異常
          4. String item = (String) listOfRawTypes.get(0); //需要顯式的類型轉(zhuǎn)換
          5. item = (String) listOfRawTypes.get(1); //拋 ClassCastException,因為 Integer 不能被轉(zhuǎn)換為 String
          6. List listOfString = new ArrayList();
          7. listOfString.add("abcd");
          8. listOfString.add(1234); //編譯錯誤,比在運行時拋異常要好
          9. item = listOfString.get(0); //不需要顯式的類型轉(zhuǎn)換 - 編譯器自動轉(zhuǎn)換

          通配符

          通配符上界

          常規(guī)使用

           
           
           
          1. public class Test {
          2. public static void printIntValue(List list) {
          3. for (Number number : list) {
          4. System.out.print(number.intValue()+" ");
          5. }
          6. System.out.println();
          7. }
          8. public static void main(String[] args) {
          9. List integerList=new ArrayList();
          10. integerList.add(2);
          11. integerList.add(2);
          12. printIntValue(integerList);
          13. List floatList=new ArrayList();
          14. floatList.add((float) 3.3);
          15. floatList.add((float) 0.3);
          16. printIntValue(floatList);
          17. } }

          輸出:

          2 2

          3 0

          非法使用

           
           
           
          1. public class Test {
          2. public static void fillNumberList(List list) {
          3. list.add(new Integer(0));//編譯錯誤
          4. list.add(new Float(1.0));//編譯錯誤
          5. }
          6. public static void main(String[] args) {
          7. List list=new ArrayList();
          8. list.add(new Integer(1));//編譯錯誤
          9. list.add(new Float(1.0));//編譯錯誤
          10. } }

          List可以代表 List或 List,為什么不能像其中加入 Integer或者 Float 呢?

          首先,我們知道 List之中只能加入 Integer。并且如下代碼是可行的:

           
           
           
          1. List list1=new ArrayList();
          2. List list2=new ArrayList();

          假設(shè)前面的例子沒有編譯錯誤,如果我們把 list1 或者 list2 傳入方法 fillNumberList,顯然都會出現(xiàn)類型不匹配的情況,假設(shè)不成立。

          因此,我們得出結(jié)論:不能往 List 中添加任意對象,除了 null。

          那為什么對 List進行迭代可以呢,因為子類必定有父類相同的接口,這正是我們所期望的。

          通配符下界

          常規(guī)使用

           
           
           
          1. public class Test {
          2. public static void fillNumberList(List list) {
          3. list.add(new Integer(0));
          4. list.add(new Float(1.0));
          5. }
          6. public static void main(String[] args) {
          7. List list=new ArrayList();
          8. list.add(new Integer(1));
          9. list.add(new Float(1.1));
          10. } }

          可以添加 Number 的任何子類,為什么呢?

          List可以代表 List,其中 T 為 Number 父類,(雖然 Number 沒有父類)。如果說,T 為 Number 的父類,我們想 List中加入 Number 的子類肯定是可以的。

          非法使用

          對 List進行迭代是不允許的。為什么呢?你知道用哪種接口去迭代 List 嗎?只有用 Object類的接口才能保證集合中的元素都擁有該接口,顯然這個意義不大。其應(yīng)用場景略。

          無界通配符

          知道了通配符的上界和下界,其實也等同于知道了無界通配符,不加任何修飾即可,單獨一個“?”。如List,“?”可以代表任意類型,“任意”也就是未知類型。

          List與 List并不等同,List是 List的子類。還有不能往 List list里添加任意對象,除了 null。

          常規(guī)使用

          1、當(dāng)方法是使用原始的 Object 類型作為參數(shù)時,如下:

           
           
           
          1. public static void printList(List list) {
          2. for (Object elem : list)
          3. System.out.println(elem + "");
          4. System.out.println();
          5. }
          6. 可以選擇改為如下實現(xiàn):

             
             
             
            1. public static void printList(List list) {
            2. for (Object elem: list)
            3. System.out.print(elem + "");
            4. System.out.println();
            5. }

            這樣就可以兼容更多的輸出,而不單純是 List,如下:

             
             
             
            1. List li = Arrays.asList(1, 2, 3);
            2. List ls = Arrays.asList("one", "two", "three");
            3. printList(li);
            4. printList(ls);

            分享題目:Java泛型需要注意的問題
            當(dāng)前地址:http://www.dlmjj.cn/article/cdgdgde.html