精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Java泛型簡(jiǎn)明教程

  前面我們提到Java集合有個(gè)缺點(diǎn),就是把一個(gè)對(duì)象“丟進(jìn)”集合里之后,集合就會(huì)“忘記”這個(gè)對(duì)象的數(shù)據(jù)類型,當(dāng)再次取出該對(duì)象時(shí),該對(duì)象的編譯類型就變成了Object類型(其運(yùn)行時(shí)類型沒(méi)變)。

    Java集合之所以被設(shè)計(jì)成這樣,是因?yàn)榧系脑O(shè)計(jì)者不知道我們會(huì)用集合來(lái)保存什么類型的對(duì)象,所以他們把集合設(shè)計(jì)成能保存任何類型的對(duì)象,只要求具有很好的通用性,但這樣做帶來(lái)如下兩個(gè)問(wèn)題:

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

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

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

    泛型集合

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

    例1

    下面將結(jié)合泛型與集合編寫(xiě)一個(gè)案例實(shí)現(xiàn)圖書(shū)信息輸出。

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

public class Book { private int Id; // 圖書(shū)編號(hào)
 private String Name; // 圖書(shū)名稱
 private int Price; // 圖書(shū)價(jià)格
 public Book(int id, String name, int price) { // 構(gòu)造方法
  this.Id = id;  this.Name = name;  this.Price = price;
 } public String toString() { // 重寫(xiě) toString()方法
  return this.Id + ", " + this.Name + "," + this.Price;
 }
}12345678910111213復(fù)制代碼類型:[java]

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

public class Test14 { public static void main(String[] args) {  // 創(chuàng)建3個(gè)Book對(duì)象
  Book book1 = new Book(1, "唐詩(shī)三百首", 8);
  Book book2 = new Book(2, "小星星", 12);
  Book book3 = new Book(3, "成語(yǔ)大全", 22);
  Map<Integer, Book> books = new HashMap<Integer, Book>(); // 定義泛型 Map 集合
  books.put(1001, book1); // 將第一個(gè) Book 對(duì)象存儲(chǔ)到 Map 中
  books.put(1002, book2); // 將第二個(gè) Book 對(duì)象存儲(chǔ)到 Map 中
  books.put(1003, book3); // 將第三個(gè) Book 對(duì)象存儲(chǔ)到 Map 中
  System.out.println("泛型Map存儲(chǔ)的圖書(shū)信息如下:");  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存儲(chǔ)的圖書(shū)信息如下:");  for (int i = 0; i < bookList.size(); i++) {
   System.out.println(bookList.get(i)); // 這里不需要類型轉(zhuǎn)換
  }
 }
}123456789101112131415161718192021222324252627復(fù)制代碼類型:[java]

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

    執(zhí)行結(jié)果如下:

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

    泛型類

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

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

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

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

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

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

    例2

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

public class Stu<N, A, S> { private N name; // 姓名
 private A age; // 年齡
 private S sex; // 性別
 // 創(chuàng)建類的構(gòu)造函數(shù)
 public Stu(N name, A age, S sex) {  this.name = name;  this.age = age;  this.sex = sex;
 } // 下面是上面3個(gè)屬性的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復(fù)制代碼類型:[java]

    接著創(chuàng)建測(cè)試類。在測(cè)試類中調(diào)用Stu類的構(gòu)造方法實(shí)例化Stu對(duì)象,并給該類中的3個(gè)屬性賦予初始值,最終需要輸出學(xué)生信息。測(cè)試類的代碼實(shí)現(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("學(xué)生信息如下:");
  System.out.println("學(xué)生姓名:" + name + ",年齡:" + age + ",性別:" + sex);
 }
}12345678910復(fù)制代碼類型:[java]

    該程序的運(yùn)行結(jié)果如下:

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

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

    泛型方法

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

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

    定義泛型方法的語(yǔ)法格式如下:

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

    例如:

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

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

    例3

    使用泛型方法打印圖書(shū)信息。定義泛型方法,參數(shù)類型使用“T”來(lái)代替。在方法的主體中打印出圖書(shū)信息。代碼的實(shí)現(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, "細(xì)學(xué) Java 編程", 28);
  List(stu); // 調(diào)用泛型方法
 }
}1234567891011復(fù)制代碼類型:[java]

    該程序中的Book類為前面示例中使用到的Book類。在該程序中定義了一個(gè)名稱為L(zhǎng)ist的方法,該方法的返回值類型為void,類型參數(shù)使用“T”來(lái)代替。在調(diào)用該泛型方法時(shí),將一個(gè)Book對(duì)象作為參數(shù)傳遞到該方法中,相當(dāng)于指明了該泛型方法的參數(shù)類型為Book。

    該程序的運(yùn)行結(jié)果如下:

1, 細(xì)學(xué) Java 編程,281復(fù)制代碼類型:[java]

    泛型的高級(jí)用法

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

    1.限制泛型可用類型

    在Java中默認(rèn)可以使用任何類型來(lái)實(shí)例化一個(gè)泛型類對(duì)象。當(dāng)然也可以對(duì)泛型類實(shí)例的類型進(jìn)行限制,語(yǔ)法格式如下:

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

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

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

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

    在上述代碼中,定義ListClass類時(shí)設(shè)置泛型類型必須實(shí)現(xiàn)List接口。例如,ArrayList和LinkedList都實(shí)現(xiàn)了List接口,所以可以實(shí)例化ListClass類。而HashMap沒(méi)有實(shí)現(xiàn)List接口,所以在實(shí)例化ListClass類時(shí)會(huì)報(bào)錯(cuò)。

    當(dāng)沒(méi)有使用extends關(guān)鍵字限制泛型類型時(shí),其實(shí)是默認(rèn)使用Object類作為泛型類型。因此,Object類下的所有子類都可以實(shí)例化泛型類對(duì)象,如圖1所示的這兩種情況。

    2.使用類型通配符

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

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

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

    其中,“<?extendsList>”作為一個(gè)整體表示類型未知,當(dāng)需要使用泛型對(duì)象時(shí),可以單獨(dú)實(shí)例化。

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

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

    在上述代碼中,同樣由于HashMap類沒(méi)有實(shí)現(xiàn)List接口,所以在編譯時(shí)會(huì)報(bào)錯(cuò)。

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

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

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

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

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

interface interface1<T1>{}interface SubClass<T1,T2,T3> implementsInterface1<T2>{}
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Java多態(tài)性
java中兩個(gè)對(duì)象的比較,equals()方法和==號(hào)的區(qū)別
Java 成員變量和成員方法
Java 8新特性2——注解的變化及類型推斷
Java必備基礎(chǔ)知識(shí)點(diǎn)(超全)
java基礎(chǔ)3
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

主站蜘蛛池模板: 辽源市| 宜良县| 商丘市| 普兰县| 巴林右旗| 桂平市| 涞水县| 盐城市| 韶山市| 临武县| 江川县| 新平| 英吉沙县| 孟津县| 呈贡县| 福泉市| 西吉县| 峨边| 临猗县| 东兰县| 南丹县| 宝丰县| 武川县| 冀州市| 江华| 平泉县| 潞城市| 曲周县| 荃湾区| 银川市| 南部县| 马山县| 炎陵县| 广德县| 巨野县| 灵璧县| 鄂尔多斯市| 北票市| 太保市| 嘉祥县| 碌曲县|