<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                java泛型在平時開發中或者閱讀項目源碼的時候都見過他,我們雖然知道它,但是大多數我們也是對他并不太了解。這個星期我花了點時間重新復習了一下泛型的一些內容,這篇文章是對復習筆記的簡單整理,里面內容只是整理一些我們經常忽視或者有很模糊的知識點。 1. 概述 2. 類型擦除 3. 泛型晉級使用 4. 通配符 5. 其他 ### 1\. 概述 泛型指的是可以將類型作為參數進行傳遞,其本質上就是類型參數化。比如:我們平時定義一個方法的時候,常會指定要傳入一個具體類對象作為參數。而如果使用泛型,那么這個具體傳入類的對象,就可以指定為某個類型,而不必指定具體的類。也就是我們將某個類型作為參數進行傳遞了。 ~~~ //普通方法 public void testValue(String s) {} //泛型方法 public <T> void testValue(T t) {} ~~~ #### 他與使用Object有什么區別? 如果我們使用Object,就要將傳入的類型強制轉換成我們需要的類型,如果傳入的類型不匹配將會導致程序包`ClassCastException`異常。比如下面的代碼,testObj()傳入的是int類型的值,程序在執行的時候將會出錯: ~~~ public void testObj(Object o){ String name= (String) o; } ~~~ 我們可以通過泛型將來實現這樣的需求: ~~~ public <O extends String> void testObj(O o) { String name = o; } ~~~ #### 使用泛型有哪些好處? * 它可以避免類型強制轉換,而引起的程序異常。 * 可以是代碼更加簡潔易度。 * 是代碼更加靈活,可定制型強。 ### 2\. 類型擦除 泛型值存在于編譯期,代碼在進入虛擬機后泛型就會會被擦除掉,這個者特性就叫做類型擦除。當泛型被擦除后,他有兩種轉換方式,第一種是如果泛型沒有設置類型上限,那么將泛型轉化成Object類型,第二種是如果設置了類型上限,那么將泛型轉化成他的類型上限。 ~~~ //未指定上限 public class Test1<T> { T t; public T getValue() { return t; } public void setVale(T t) { this.t = t; } } //指定上限 public class Test2<T extends String> { T t; public T getT() { return t; } public void setT(T t) { this.t = t; } } //通過反射調用獲取他們的屬性類型 @Test public void testType1() { Test1<String> test1 = new Test1<>(); test1.setVale("11111"); Class<? extends Test1> aClass = test1.getClass(); for (Field field : aClass.getDeclaredFields()) { System.out.println("Test1屬性:" + field.getName() + "的類型為:" + field.getType().getName()); } Test2 test2 = new Test2(); test2.setT("2222"); Class<? extends Test2> aClass2 = test2.getClass(); for (Field field : aClass2.getDeclaredFields()) { System.out.println("test2屬性:" + field.getName() + "的類型為:" + field.getType().getName()); } } ~~~ 上面方法打印的結果: ~~~ Test1屬性:t的類型為:java.lang.Object Test2屬性:t的類型為:java.lang.String ~~~ ### 3\. 泛型晉級使用 #### 繼承關系 即設置泛型上限,傳入的泛型必須是String類型或者是他的子類 > 這里有一個小小的坑,感謝以為熱心網友的反饋。如果讀者看到這段請想一想String的特性。這個問題在文章末尾的評論去有答案。 ~~~ public <T extends String> void testType(T t) {} ~~~ #### 依賴關系的使用 泛型間可以存在依賴關系,比如下面的C是繼承自E。即傳入的類型是E類型或者是E類型的子類 ~~~ public <E, C extends E> void testDependys(E e, C c) {} ~~~ ### 4\. 通配符 當我們不知道或者不關心實際操作類型的時候我們可以使用`無限通配符`,當我們不指定或者不關心操作類型,但是又想進行一定范圍限制的時候,我們可以通過添加`上限`或`下限`來起到限制作用。 #### 無限通配符 無限通配符表示的是未知類型,表示不關心或者不能確定實際操作的類型,一般配合容器類使用。 ~~~ public void testV(List<?> list) {} ~~~ 需要注意的是: 無限通配符只能讀的能力,沒有寫的能力。 ~~~ public void testV(List<?> list) { Object o = list.get(0); //編譯器不允許該操作 // list.add("jaljal"); } ~~~ 上面的List為無限通配符,他只能使用get()獲取元素,但不能使用add()方法添加元素。(即使修改元素也不被允許) #### 定義了上限,期只有讀的能力。此方式表示參數化的類型可能是所`指定的類型`,或者是`此類型的子類`。 ~~~ //t1要么是Test2,要么是Test2的子類 public void testC(Test1<? extends Test2> t1) { Test2 value = t1.getValue(); System.out.println("testC中的:" + value.getT()); } ~~~ #### 定義了下限,有讀的能力以及部分寫的能力,子類可以寫入父類。此方式表示參數化的類型可能是`指定的類型`,或者是`此類型的父類` ~~~ //t1要么是Test5,要么是Test5的父類 public void testB(Test1<? super Test5> t1) { //子類代替父類 Test2 value = (Test2) t1.getValue(); System.out.println(value.getT()); } ~~~ #### 通配符不能用作返回值 如果返回值依賴類型參數,不能使用通配符作為返回值。可以使用類型參數返回方式: ~~~ public <T> T testA(T t, Test1<T> test1) { System.out.println("這是傳入的T:" + t); t = test1.t; System.out.println("這是賦值后的T:" + t); return t; } 復制代碼 ~~~ * 要從泛型類取數據時,用extends; * 要往泛型類寫數據時,用super; * 既要取又要寫,就不用通配符(即extends與super都不用)。 > 泛型中只有通配符可以使用super關鍵字,類型參數不支持 這種寫法 ### 5\. 其他 #### 什么時候使用通配符 * 通配符形式和類型參數經常`配合使用` * `類型參數`的形式都可以`替代`通配符的形式 * `能用通配符的就用通配符`,因為通配符形式上往往更為`簡單`、`可讀性也更好`。 * 類型參數之間有`依賴關系`、`返回值`依賴類型參數或者需要`寫操作`,則只能用`類型參數`。 #### 查看源碼使用 如果想查找源碼中的相關使用可以`Collections`類的的下面這些方法: ~~~ public static <T extends Comparable<? super T>> void sort(List<T> list) public static <T> void sort(List<T> list, Comparator<? super T> c) public static <T> void copy(List<? super T> dest, List<? extends T> src) public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) ~~~ 轉載至---鏈接:https://juejin.cn/post/6844903833391333390
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看