<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 一、概述 前面我們提到[](http://c.biancheng.net/java/) Java 集合有個缺點,就是把一個對象“丟進”集合里之后,集合就會“忘記”這個對象的數據類型,當再次取出該對象時,該對象的編譯類型就變成了 Object 類型(其運行時類型沒變)。 Java 集合之所以被設計成這樣,是因為集合的設計者不知道我們會用集合來保存什么類型的對象,所以他們把集合設計成能保存任何類型的對象,只要求具有很好的通用性,但這樣做帶來如下兩個問題: 1. 集合對元素類型沒有任何限制,這樣可能引發一些問題。例如,想創建一個只能保存 Dog 對象的集合,但程序也可以輕易地將 Cat 對象“丟”進去,所以可能引發異常。 2. 由于把對象“丟進”集合時,集合丟失了對象的狀態信息,集合只知道它盛裝的是 Object,因此取出集合元素后通常還需要進行強制類型轉換。這種強制類型轉換既增加了編程的復雜度,也可能引發 ClassCastException 異常。 所以為了解決上述問題,從 Java 1.5 開始提供了泛型。泛型可以在編譯的時候檢查類型安全,并且所有的強制轉換都是自動和隱式的,提高了代碼的重用率。 泛型本質上是提供類型的“類型參數”,也就是參數化類型。我們可以為類、接口或方法指定一個類型參數,通過這個參數限制操作的數據類型,從而保證類型轉換的絕對安全。 ## 二、泛型集合 【例題】下面將結合泛型與集合編寫一個案例實現圖書信息輸出。 ``` public class Book { private int id; private String name; private int price; public Book() {} public Book(int id, String name, int price) { this.id = id; this.name = name; this.price = price; } public String toString() { return this.id + ", " + this.name + ", " + this.price; } } public class BookTest { public static void main(String[] args) { // 定義泛型 Map 集合 Map<Integer, Book> bookMap = new HashMap<Integer, Book>(); bookMap.put(1001, new Book(1, "唐詩三百首", 8)); bookMap.put(1002, new Book(2, "成語大全", 12)); bookMap.put(1003, new Book(3, "新華字典", 22)); System.out.println("泛型Map存儲的圖書信息如下:"); for (int id : books.keySet()) { System.out.print(id + "---"); System.out.println(bookMap.get(id)); // 不需要類型轉換 } } } ``` 【選擇】以下語句正確的是()(選擇兩項) ``` A List<String> list = new ArrayList<String>(); B List<Integer> list = new ArrayList<>(); C List<Aniaml> list = new ArrayList<Cat>(); // 已知 Cat 是 Animal 的子類 D List<Object> list = new ArrayList<Integer>(); ``` ## 三、泛型類 除了可以定義泛型集合之外,還可以直接限定泛型類的類型參數。語法格式如下: ``` public class 類名<類型參數1, 類型參數2, …>{} ``` 泛型類一般用于類中的屬性類型不確定的情況下。在聲明屬性時,使用下面的語句: ``` private 類型參數1 屬性名稱1; private 類型參數2 屬性名稱2; ``` 在實例化泛型類時,需要指明泛型類中的類型參數,并賦予泛型類屬性相應類型的值。 【例題】下面的示例代碼創建了一個表示學生的泛型類,該類中包括 3 個屬性,分別是姓名、年齡和性別。 ``` public class Student<N, A> { private N name; // 姓名 private A age; // 年齡 public Student() {} public Student(N name, A age) { this.name = name; this.age = age; } // 省略 getter setter... } public class StudentTest { public static void main(String[] args) { Student<String, Integer> stu = new Student<>("小明", 20); String name = stu.getName(); Integer age = stu.getAge(); System.out.println("學生信息如下:"); System.out.println("學生姓名:" + name + ",年齡:" + age); } } ``` 在該程序的 Student 類中,定義了 2 個類型參數,分別使用 N 和 A 來代替,同時實現了這 2 個屬性的 setter/getter 方法。在主類中,調用 Student 類的構造函數創建了 Student 類的對象,同時指定 2 個類型參數,分別為 String 和 Integer。在獲取學生姓名、年齡時,不需要類型轉換,程序隱式地將 Object 類型的數據轉換為相應的數據類型。 ## 四、泛型方法 泛型同樣可以在類中包含參數化的方法,而方法所在的類可以是泛型類,也可以不是泛型類。 泛型方法使得該方法能夠獨立于類而產生變化。如果使用泛型方法可以取代類泛型化,那么就應該只使用泛型方法。另外,對一個 static 的方法而言,無法訪問泛型類的類型參數。因此,如果 static 方法需要使用泛型能力,就必須使其成為泛型方法。 定義泛型方法的語法格式如下: ``` [訪問權限修飾符] [static] [final] <類型參數列表> 返回值類型方法名([形式參數列表]) ``` 【例題】使用泛型方法執行動物喂食。 ``` public abstract class Animal { public abstract void eat(); } public class Cat extends Animal { public void eat() { System.out.println("cat eat ..."); } } public class Dog extends Animal { public void eat() { System.out.println("dog eat ..."); } } public class AnimalTest { public static <T> void feed(T animal) { if (animal != null && animal instanceof Animal) { animal.eat(); } } public static void main(String[] args) { feed(new Cat()); feed(new Dog()); } } ``` ## 五、泛型的高級用法 ### 5.1 限制泛型可用類型 在 Java 中默認可以使用任何類型來實例化一個泛型類對象。當然也可以對泛型類實例的類型進行限制,語法格式如下: ``` class 類名稱<T extends anyClass> ``` 其中,anyClass 指某個接口或類。使用泛型限制后,泛型類的類型必須實現或繼承 anyClass 這個接口或類。無論 anyClass 是接口還是類,在進行泛型限制時都必須使用 extends 關鍵字。 【例題】在下面的示例代碼中創建了一個 Student 類,并對該類的類型限制為只能是繼承 Number 類的類。 ``` // 限制 Student 的泛型類型必須繼承 Number 類 public class Student<T extends Number> { private T age; public Student(T age) { this.age = age; } public static void main(String[] args) { // 實例化使用 Integer 的泛型類 Student,正確 Student<Integer> s1 = new Student<Integer>(15); // 實例化使用 Long 的泛型類 Student,正確 Student<Long> s2 = new Student<Long>(15L); // 實例化使用 String 的泛型類 Student,錯誤 Student<String> s3 = new Student<String>("hello"); } } ``` 當沒有使用 extends 關鍵字限制泛型類型時,其實是默認使用 Object 類作為泛型類型。如下等價: ``` public class SomeClass<T> {} public class SomeClass<T extends Object> {} ``` 【閱讀】已知如下代碼,運行結果為() ``` public abstract class Person { protected String name; // getter setter ... public abstract void display(); } public class Teacher extends Person { public Teacher(String name) { this.name = name; } public void display() { System.out.println(this.getName() + "在講課"); } } public class Student extends Person { public Student(String name) { this.name = name; } public void display() { System.out.println(this.getName() + "在學習"); } } public class Test { public <T extends Person> void display(T t) { t.display(); } public static void main(String[] args) { Test test = new Test(); test.display(new Teacher("王老師")); test.display(new Student("張三")); test.display("李四在學習"); } } ``` ### 5.2 使用類型通配符 Java 中的泛型還支持使用類型通配符,在創建一個泛型類對象時限制這個泛型類的類型必須實現或繼承某個接口或類。 使用泛型類型通配符的語法格式如下: ``` 泛型類名稱<? extends Number> a = null; ``` 【例題】下面的示例代碼演示了類型通配符的使用。 ``` public class Stu<T> { private T attr; public Stu() {} public Stu(T attr) { this.attr = attr; } } public class StuTest { public static void main(String[] args) { Stu<? extends Number> s = null; s = new Stu<Integer>(); // 正確 s = new Stu<Long>(); // 正確 s = new Stu<String>(); // 錯誤 } } ``` ### 5.3 繼承泛型類和實現泛型接口 定義為泛型的類和接口也可以被繼承和實現。 ``` public interface MyInter<T1> {} public class Father<T2> {} public class Son<T1, T2, T3> extends Father<T2> implements MyInter<T1> {} ``` 如果要在 Son 類繼承 Father 類時保留父類的泛型類型,需要在繼承時指定,否則直接使用 extends Father 語句進行繼承操作,此時 T1、T2 和 T3 都會自動變為 Object,所以一般情況下都將父類的泛型類型保留。
                  <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>

                              哎呀哎呀视频在线观看