作為一個曾被泛型弄得死去活來的小辣雞秸苗,這篇文章將致力于給大家以最清新舒服的方式來把泛型講的清清爽爽~
首先我想以集合來為泛型開個頭召娜,現(xiàn)在咱們這里有一個需求:集合里面有字符串類的數(shù)據(jù),我們要把它打印出來惊楼,代碼很簡單
public class TestDemo {
public static void main(String[] args) {
ArrayList a=new ArrayList();
a.add("java01");//添加
a.add("java02");
a.add("java03");//a:java01,java02,java03
//a.add(4);//加入一個整形
Iterator it=a.iterator();
while(it.hasNext())
{
String s=(String)it.next();
sop(s);
}
}
static void sop(Object e) {
System.out.println(e);
}
}
一天有一個好事者一不小心加入了一個整形變量玖瘸,編譯沒有問題秸讹,但是在運(yùn)行時會打印錯誤(把上文代碼中的注釋去掉,編譯
java01
java02
java03
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at TestDemo.main(TestDemo.java:21)
代碼拋了一個異常雅倒,問題在于Integer類型不能強(qiáng)轉(zhuǎn)為String類型
問題來了璃诀,集合作為一個容器對于所有的對象都統(tǒng)統(tǒng)接收,那么我們能不能對容器加以限制蔑匣,比如說劣欢,我們就要String類型的,其他的都統(tǒng)統(tǒng)的不接受裁良?
答案是肯定可以的凿将,主jio登場~(BGM ing.....
泛型
泛型能夠限制傳進(jìn)來的類型
可能說起來有些抽象,我們還是用上面那個例子來說明趴久,見代碼
ArrayList a=new ArrayList();
修改一下
ArrayList<String> a=new ArrayList<String>();
這個時候丸相,我們再試著添加整型4,編譯報(bào)錯
Multiple markers at this line
- The method add(int, String) in the type ArrayList<String> is not applicable for the arguments
(int)
- Type safety: The method add(Object) belong
意思大概是int類型的不能應(yīng)用類型是String的添加方法
我們已經(jīng)成功的用泛型來限定了傳進(jìn)去的類型了彼棍,在創(chuàng)建對象時<>中傳入合適的類型
問題來了灭忠,使用泛型需要什么條件呢?
我們來看看ArrayList的JDK文檔
Class ArrayList<E>
在ArrayList后面添加了<E>
我們在看看類中的方法
比如說add(E e)中參數(shù)的類型和Class ArrayList<E>中的E是一致的
也就是說我們在限定我們創(chuàng)建ArrayList時候的類型參數(shù)和后面方法中的參數(shù)是一致的座硕,這里的E其實(shí)也就是Element的含義
需要注意的是JDK中的Iterator也允許泛型
這里再給出完整的代碼
public class TestDemo {
public static void main(String[] args) {
ArrayList<String> a=new ArrayList<String>();
a.add("java01");//添加
a.add("java02");
a.add("java03");//a:java01,java02,java03
Iterator<String> it=a.iterator();
while(it.hasNext())
{
//String s-(String)it.next();
String s=it.next();
sop(s);
}
}
static void sop(Object e) {
System.out.println(e);
}
}
這里可以給出兩個添加泛型后的小結(jié)論
1弛作、限定容器中的元素的內(nèi)容
2、避免獲得容器中內(nèi)容的元素時需要強(qiáng)轉(zhuǎn)
這里提出一個問題华匾,是否我們自己能夠使用泛型映琳?
答案是肯定的,接下來給大家介紹常見的情況下使用泛型
類中加泛型
類中所有用到類定義時使用的類型的方法
也就是說蜘拉,方法中傳入的參數(shù)只要和定義類時參數(shù)一致萨西,那么創(chuàng)建對象時就確定了
public class Person<E> {
void show(E e)
{
System.out.println("show-----"+e);
}
}
import javax.print.attribute.standard.MediaSize.Other;
public class TestDemo {
public static void main(String[] args) {
Person<String> p=new Person<String>();
String s="abc";
p.show(s);
}
static void sop(Object e) {
System.out.println(e);
}
}
打印一下
show-----abc
Person<E>和show(E e)中的E是同一個E,傳入的類型就被確定了
我想讓方法中使用自己的泛型行不行?也就是方法中的泛型與類無關(guān)
聰明的JAVA會告訴你旭旭,答案肯定也是可以的
方法中添加泛型
格式:修飾符+<E>+返回類型+方法名+參數(shù)
見代碼
//方法中單獨(dú)設(shè)置泛型
public class Person<E> {
void show(E e)
{
System.out.println("show-----"+e);
}
public <T> void method(T t)
{
System.out.println("method----"+t);
}
public static <R> void function(R r)
{
System.out.println("function----"+r);
}
}
public class TestDemo {
public static void main(String[] args) {
Person<String> p=new Person<String>();
String s="abc";
p.show(s);
int num=201314;
p.method(num);
Person.function(520);
}
static void sop(Object e) {
System.out.println(e);
}
}
打印一下
show-----abc
method----201314
function----520
又有同學(xué)舉手手說:好像泛型在很多地方都能夠加
答案是肯定的谎脯,接下來我們一起來看還有那些地方能夠加
接口中設(shè)置泛型
格式:interface+接口名+<E>
interface Inter<M>{
void show(M m);
<M> void method(M m);
}
public class InterTest implements Inter<String>{
@Override
public void show(String m) {
// TODO Auto-generated method stub
System.out.println("show---"+m);
}
@Override
public <M> void method(M m) {
// TODO Auto-generated method stub
System.out.println("method----"+m);
}
}
到這里了,我們來做一個小總結(jié)
泛型的使用非常廣泛持寄,類源梭、方法、接口都可以使用泛型作為限定類型稍味,其實(shí)它的本質(zhì)就是打破了Object的使用废麻,并且很好的維持了多態(tài)(因?yàn)楸苊饬藦?qiáng)轉(zhuǎn))
好事者又不服,認(rèn)為我們既然利用泛型在創(chuàng)建時限定了類型模庐,那么我現(xiàn)在有一個需求:我有一個Person類烛愧,還有一個Person的子類Student,我想把這兩個類都打印出他們的屬性,我想用一個通用的辦法來打印
這個需求提的很好
泛型限定符
泛型不光支持任何單一類型屑彻,還支持具有繼承關(guān)系的類型
格式:<? extends 類型>允許某一種類型極其子類
那么這里的需求很好的可以滿足
//創(chuàng)建嗎一個基本Person類
public class Person {
private String name;
private int age;
Person(String name,int age)
{
this.age=age;
this.name=name;
}
void show()
{
System.out.println("person-----"+name+age);
}
}
//Person類的子類
public class student extends Person {
private String name;
private int age;
private String xuehao;
student(String name, int age,String xuehao) {
super(name, age);
this.xuehao=xuehao;
// TODO Auto-generated constructor stub
}
void show() {
System.out.println("stu----"+name+age+xuehao);
}
}
//需求:用一種通用的方法打印Person和student類的基本屬性
public class TestDemo {
public static void main(String[] args) {
ArrayList<Person> per_al=new ArrayList<Person>();
per_al.add(new Person("xiaoming01",14));
per_al.add(new Person("xiaoming02",12));
per_al.add(new Person("xiaoming03",13));
per_al.add(new Person("xiaoming04",42));
per_al.add(new Person("xiaoming05",16));
ArrayList<student> stu_al=new ArrayList<student>();
stu_al.add(new student("xiaoming01",14,"201514160101"));
stu_al.add(new student("xiaoming02",14,"201514160102"));
stu_al.add(new student("xiaoming03",14,"201514160103"));
stu_al.add(new student("xiaoming04",14,"201514160104"));
printColl(per_al);
printColl(stu_al);
}
public static void printColl(ArrayList<? extends Person> al)
{
Iterator<? extends Person> it=al.iterator();
while(it.hasNext())
it.next().show();
}
static void sop(Object e) {
System.out.println(e);
}
}
打印一下
person-----xiaoming0114
person-----xiaoming0212
person-----xiaoming0313
person-----xiaoming0442
person-----xiaoming0516
stu----null0201514160101
stu----null0201514160102
stu----null0201514160103
stu----null0201514160104
這樣子佛寿,Iterator中的泛型的類型就允許接收Person和Person的子類
我們不光可以接收類及其子類艰猬,我們還可以接收類及其父類
格式:<? super student>
總結(jié)
在創(chuàng)建類威彰、方法纺铭、接口的時候利用了泛型限定符,我們可以定義單類型搏恤,類以及其父類违寿,類以及子類三種形式