乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Java泛型簡明教程

       碼農(nóng)9527 2021-09-24

        前面我們提到Java集合有個缺點,就是把一個對象“丟進”集合里之后,集合就會“忘記”這個對象的數(shù)據(jù)類型,當再次取出該對象時,該對象的編譯類型就變成了Object類型(其運行時類型沒變)。

          Java集合之所以被設計成這樣,是因為集合的設計者不知道我們會用集合來保存什么類型的對象,所以他們把集合設計成能保存任何類型的對象,只要求具有很好的通用性,但這樣做帶來如下兩個問題:

          1、集合對元素類型沒有任何限制,這樣可能引發(fā)一些問題。例如,想創(chuàng)建一個只能保存Dog對象的集合,但程序也可以輕易地將Cat對象“丟”進去,所以可能引發(fā)異常。

          2、由于把對象“丟進”集合時,集合丟失了對象的狀態(tài)信息,集合只知道它盛裝的是Object,因此取出集合元素后通常還需要進行強制類型轉(zhuǎn)換。這種強制類型轉(zhuǎn)換既增加了編程的復雜度,也可能引發(fā)ClassCastException異常。

          所以為了解決上述問題,從Java1.5開始提供了泛型。泛型可以在編譯的時候檢查類型安全,并且所有的強制轉(zhuǎn)換都是自動和隱式的,提高了代碼的重用率。本節(jié)將詳細介紹Java中泛型的使用。

          泛型集合

          泛型本質(zhì)上是提供類型的“類型參數(shù)”,也就是參數(shù)化類型。我們可以為類、接口或方法指定一個類型參數(shù),通過這個參數(shù)限制操作的數(shù)據(jù)類型,從而保證類型轉(zhuǎn)換的絕對安全。

          例1

          下面將結合泛型與集合編寫一個案例實現(xiàn)圖書信息輸出。

          1)首先需要創(chuàng)建一個表示圖書的實體類Book,其中包括的圖書信息有圖書編號、圖書名稱和價格。Book類的具體代碼如下:

      public class Book { private int Id; // 圖書編號
       private String Name; // 圖書名稱
       private int Price; // 圖書價格
       public Book(int id, String name, int price) { // 構造方法
        this.Id = id;  this.Name = name;  this.Price = price;
       } public String toString() { // 重寫 toString()方法
        return this.Id + ", " + this.Name + "," + this.Price;
       }
      }12345678910111213復制代碼類型:[java]

          2)使用Book作為類型創(chuàng)建Map和List兩個泛型集合,然后向集合中添加圖書元素,最后輸出集合中的內(nèi)容。具體代碼如下:

      public class Test14 { public static void main(String[] args) {  // 創(chuàng)建3個Book對象
        Book book1 = new Book(1, "唐詩三百首", 8);
        Book book2 = new Book(2, "小星星", 12);
        Book book3 = new Book(3, "成語大全", 22);
        Map<Integer, Book> books = new HashMap<Integer, Book>(); // 定義泛型 Map 集合
        books.put(1001, book1); // 將第一個 Book 對象存儲到 Map 中
        books.put(1002, book2); // 將第二個 Book 對象存儲到 Map 中
        books.put(1003, book3); // 將第三個 Book 對象存儲到 Map 中
        System.out.println("泛型Map存儲的圖書信息如下:");  for (Integer id : books.keySet()) {   // 遍歷鍵
         System.out.print(id + "——");
         System.out.println(books.get(id)); // 不需要類型轉(zhuǎn)換
        }
        List<Book> bookList = new ArrayList<Book>(); // 定義泛型的 List 集合
        bookList.add(book1);
        bookList.add(book2);
        bookList.add(book3);
        System.out.println("泛型List存儲的圖書信息如下:");  for (int i = 0; i < bookList.size(); i++) {
         System.out.println(bookList.get(i)); // 這里不需要類型轉(zhuǎn)換
        }
       }
      }123456789101112131415161718192021222324252627復制代碼類型:[java]

          在該示例中,第7行代碼創(chuàng)建了一個鍵類型為Integer、值類型為Book的泛型集合,即指明了該Map集合中存放的鍵必須是Integer類型、值必須為Book類型,否則編譯出錯。在獲取Map集合中的元素時,不需要將books.get(id);獲取的值強制轉(zhuǎn)換為Book類型,程序會隱式轉(zhuǎn)換。在創(chuàng)建List集合時,同樣使用了泛型,因此在獲取集合中的元素時也不需要將bookList.get(i)代碼強制轉(zhuǎn)換為Book類型,程序會隱式轉(zhuǎn)換。

          執(zhí)行結果如下:

      泛型Map存儲的圖書信息如下:1001——1, 唐詩三百首,81003——3, 成語大全,221002——2, 小星星,12泛型List存儲的圖書信息如下:1, 唐詩三百首,82, 小星星,123, 成語大全,2212345678復制代碼類型:[java]

          泛型類

          除了可以定義泛型集合之外,還可以直接限定泛型類的類型參數(shù)。語法格式如下:

      public class class_name<data_type1,data_type2,…>{}1復制代碼類型:[java]

          其中,class_name表示類的名稱,data_type1等表示類型參數(shù)。Java泛型支持聲明一個以上的類型參數(shù),只需要將類型用逗號隔開即可。

          泛型類一般用于類中的屬性類型不確定的情況下。在聲明屬性時,使用下面的語句:

      private data_type1 property_name1;private data_type2 property_name2;12復制代碼類型:[java]

          該語句中的data_type1與類聲明中的data_type1表示的是同一種數(shù)據(jù)類型。

          例2

          在實例化泛型類時,需要指明泛型類中的類型參數(shù),并賦予泛型類屬性相應類型的值。例如,下面的示例代碼創(chuàng)建了一個表示學生的泛型類,該類中包括3個屬性,分別是姓名、年齡和性別。

      public class Stu<N, A, S> { private N name; // 姓名
       private A age; // 年齡
       private S sex; // 性別
       // 創(chuàng)建類的構造函數(shù)
       public Stu(N name, A age, S sex) {  this.name = name;  this.age = age;  this.sex = sex;
       } // 下面是上面3個屬性的setter/getter方法
       public N getName() {  return name;
       } public void setName(N name) {  this.name = name;
       } public A getAge() {  return age;
       } public void setAge(A age) {  this.age = age;
       } public S getSex() {  return sex;
       } public void setSex(S sex) {  this.sex = sex;
       }
      }123456789101112131415161718192021222324252627282930復制代碼類型:[java]

          接著創(chuàng)建測試類。在測試類中調(diào)用Stu類的構造方法實例化Stu對象,并給該類中的3個屬性賦予初始值,最終需要輸出學生信息。測試類的代碼實現(xiàn)如下: 

      public class Test14 { public static void main(String[] args) {
        Stu<String, Integer, Character> stu = new Stu<String, Integer, Character>("張曉玲", 28, '女');
        String name = stu.getName();
        Integer age = stu.getAge();
        Character sex = stu.getSex();
        System.out.println("學生信息如下:");
        System.out.println("學生姓名:" + name + ",年齡:" + age + ",性別:" + sex);
       }
      }12345678910復制代碼類型:[java]

          該程序的運行結果如下:

      學生信息如下:
      學生姓名:張曉玲,年齡:28,性別:女12復制代碼類型:[java]

          在該程序的Stu類中,定義了3個類型參數(shù),分別使用N、A和S來代替,同時實現(xiàn)了這3個屬性的setter/getter方法。在主類中,調(diào)用Stu類的構造函數(shù)創(chuàng)建了Stu類的對象,同時指定3個類型參數(shù),分別為String、Integer和Character。在獲取學生姓名、年齡和性別時,不需要類型轉(zhuǎn)換,程序隱式地將Object類型的數(shù)據(jù)轉(zhuǎn)換為相應的數(shù)據(jù)類型。

          泛型方法

          到目前為止,我們所使用的泛型都是應用于整個類上。泛型同樣可以在類中包含參數(shù)化的方法,而方法所在的類可以是泛型類,也可以不是泛型類。也就是說,是否擁有泛型方法,與其所在的類是不是泛型沒有關系。

          泛型方法使得該方法能夠獨立于類而產(chǎn)生變化。如果使用泛型方法可以取代類泛型化,那么就應該只使用泛型方法。另外,對一個static的方法而言,無法訪問泛型類的類型參數(shù)。因此,如果static方法需要使用泛型能力,就必須使其成為泛型方法。

          定義泛型方法的語法格式如下:

      [訪問權限修飾符] [static] [final] <類型參數(shù)列表> 返回值類型 方法名([形式參數(shù)列表])1復制代碼類型:[java]

          例如:

      public static <T> List find(Class<T> cs,int userId){}1復制代碼類型:[java]

          一般來說編寫Java泛型方法,其返回值類型至少有一個參數(shù)類型應該是泛型,而且類型應該是一致的,如果只有返回值類型或參數(shù)類型之一使用了泛型,那么這個泛型方法的使用就被限制了。下面就來定義一個泛型方法,具體介紹泛型方法的創(chuàng)建和使用。

          例3

          使用泛型方法打印圖書信息。定義泛型方法,參數(shù)類型使用“T”來代替。在方法的主體中打印出圖書信息。代碼的實現(xiàn)如下:

      public class Test16 { public static <T> void List(T book) { // 定義泛型方法
        if (book != null) {
         System.out.println(book);
        }
       } public static void main(String[] args) {
        Book stu = new Book(1, "細學 Java 編程", 28);
        List(stu); // 調(diào)用泛型方法
       }
      }1234567891011復制代碼類型:[java]

          該程序中的Book類為前面示例中使用到的Book類。在該程序中定義了一個名稱為List的方法,該方法的返回值類型為void,類型參數(shù)使用“T”來代替。在調(diào)用該泛型方法時,將一個Book對象作為參數(shù)傳遞到該方法中,相當于指明了該泛型方法的參數(shù)類型為Book。

          該程序的運行結果如下:

      1, 細學 Java 編程,281復制代碼類型:[java]

          泛型的高級用法

          泛型的用法非常靈活,除在集合、類和方法中使用外,本節(jié)將從三個方面介紹泛型的高級用法,包括限制泛型可用類型、使用類型通配符、繼承泛型類和實現(xiàn)泛型接口。

          1.限制泛型可用類型

          在Java中默認可以使用任何類型來實例化一個泛型類對象。當然也可以對泛型類實例的類型進行限制,語法格式如下:

      class 類名稱<T extends anyClass>1復制代碼類型:[java]

          其中,anyClass指某個接口或類。使用泛型限制后,泛型類的類型必須實現(xiàn)或繼承anyClass這個接口或類。無論anyClass是接口還是類,在進行泛型限制時都必須使用extends關鍵字。

          例如,在下面的示例代碼中創(chuàng)建了一個ListClass類,并對該類的類型限制為只能是實現(xiàn)List接口的類。

      // 限制ListClass的泛型類型必須實現(xiàn)List接口public class ListClass<T extends List> { public static void main(String[] args) {  // 實例化使用ArrayList的泛型類ListClass,正確
        ListClass<ArrayList> lc1 = new ListClass<ArrayList>();  // 實例化使用LinkedList的泛型類LlstClass,正確
        ListClass<LinkedList> lc2 = new ListClass<LinkedList>();  // 實例化使用HashMap的泛型類ListClass,錯誤,因為HasMap沒有實現(xiàn)List接口
        // ListClass<HashMap> lc3=new ListClass<HashMap>();
       }
      }123456789101112復制代碼類型:[java]

          在上述代碼中,定義ListClass類時設置泛型類型必須實現(xiàn)List接口。例如,ArrayList和LinkedList都實現(xiàn)了List接口,所以可以實例化ListClass類。而HashMap沒有實現(xiàn)List接口,所以在實例化ListClass類時會報錯。

          當沒有使用extends關鍵字限制泛型類型時,其實是默認使用Object類作為泛型類型。因此,Object類下的所有子類都可以實例化泛型類對象,如圖1所示的這兩種情況。

          2.使用類型通配符

          Java中的泛型還支持使用類型通配符,它的作用是在創(chuàng)建一個泛型類對象時限制這個泛型類的類型必須實現(xiàn)或繼承某個接口或類。

          使用泛型類型通配符的語法格式如下:

      泛型類名稱<? extends List>a = null;1復制代碼類型:[java]

          其中,“<?extendsList>”作為一個整體表示類型未知,當需要使用泛型對象時,可以單獨實例化。

          例如,下面的示例代碼演示了類型通配符的使用。

      A<? extends List>a = null;
      a = new A<ArrayList> (); // 正確b = new A<LinkedList> (); // 正確c = new A<HashMap> (); // 錯誤1234復制代碼類型:[java]

          在上述代碼中,同樣由于HashMap類沒有實現(xiàn)List接口,所以在編譯時會報錯。

          3.繼承泛型類和實現(xiàn)泛型接口

          定義為泛型的類和接口也可以被繼承和實現(xiàn)。例如下面的示例代碼演示了如何繼承泛型類。

      public class FatherClass<T1>{}public class SonClass<T1,T2,T3> extents FatherClass<T1>{}12復制代碼類型:[java]

          如果要在SonClass類繼承FatherClass類時保留父類的泛型類型,需要在繼承時指定,否則直接使用extendsFatherClass語句進行繼承操作,此時T1、T2和T3都會自動變?yōu)镺bject,所以一般情況下都將父類的泛型類型保留。

          下面的示例代碼演示了如何在泛型中實現(xiàn)接口。

      interface interface1<T1>{}interface SubClass<T1,T2,T3> implementsInterface1<T2>{}

        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多