泛型
簡介
-
集合存儲數據底層是利用
Object
來接收的,意思是說如果不對類型加以限制,所有數據類型柔和在一起,這時如何保證數據的安全性呢(如果不限制存入的數據類型,任何數據都能存入,當我們取出數據進行強轉時無法保證成功,比如字母字符串是無法轉為數字的)。所以從 JDK5 以后,引入了一個新特性 — 泛型,提供編譯時類型安全檢測機制,可以對存入的內容類型加以限制。 -
泛型允許在定義類,接口時通過一個標識類表示其中某個屬性的類型或者某個方法的返回值及參數類型。本質是參數化類型(將類型作為參數由用戶傳遞)
-
這種參數類型可以用在類,接口和方法當中,分別稱為泛型類,泛型接口和泛型方法。
代碼演示
自定義了一個簡單的集合類,用于簡單演示泛型的作用
//自定義集合類
public class MyArrayList<E> {int size = 0;Object[] arr = new Object[10];//限制插入集合的類型public void add(E item) {arr[size] = item;size ++;}//返回值類型確定public E get(int idx) {return (E) arr[idx];}
}//演示
public static void main(String[] args) {MyArrayList<Integer> arrayList = new MyArrayList<>();arrayList.add(100);Integer integer = arrayList.get(0);System.out.println(integer);
}
使用泛型
規范泛型使用字母表示的信息
- T:Type (Java類),當類中屬性要使用時可以用該字母表示
- E:Element,在集合中使用,表示集合中元素的類型
- K:Key(鍵),在表示鍵值對的時候使用
- V:Value(值),在表示鍵值對的時候使用
- N:Number(數值類型)
- ?:表示不確定的 Java 類型
泛型類
格式:public class 類名<泛型>
注意事項:泛型類型必須是引用數據類型。基本數據類型不可以,定義泛型類,在類后面添加尖角號,尖角號內部填類型參數,可以有多個參數,參數之間使用逗號分隔。
代碼:
//泛型類
public class User<T> {private T value;public User() {}public User(T value) {this.value = value;}public T getValue() {return value;}public void setValue(T value) {this.value = value;}
}//測試
public static void main(String[] args) {User<Integer> user = new User<>();user.setValue(250);Integer value = user.getValue();
}
泛型接口
格式:public interface 類名<泛型>
代碼:
//泛型接口
public interface Play<T>{void show(T name);
}
class Impl1<T> implements Play<T> {@Overridepublic void show(T name) {System.out.println(name);}
}//測試
public class Main {public static void main(String[] args) {Impl1<String> impl1 = new Impl1<>();impl1.show("梨花");}
}
泛型方法
在調用方法時才去指名方法的參數和返回值的類型
代碼:
public class Method {//無返回值public static <T> void method1(T value) {System.out.println(value);}有返回值public static <T> T method2(T value) {return value;}
}
泛型通配符
用于解決泛型之間的引用傳遞的特殊語法,主要分為三種情況
- <?> :無邊界的通配符,主要作用是讓泛型能夠接受未知類型的數據。在沒有賦值之前,表示可以接受任何數據類型,賦值后,不能往里面添加元素。
- <? extends E>:固定上邊界的通配符,了解這個之前看看幾個概念
- 協變:在使用父類類型的場景的地方可以改用子類類型(父類應用指向子類對象)
- 逆變:在使用子類類型的場景的地方可以改用父類類型(子類引用指向父類對象)
- 不變:不能做到以上兩點
數組是可以支持協變(父類引用指向子類)。泛型是不支持協變的。這種設計大大降低了程序的靈活性,為了解決這個問題,設計出固定上邊界的通配符。能夠接受指定類及其子類類型的數據。雖然使用的是 extends 關鍵字,但是不限于繼承關系,接口引用關系也可以.
public class Method {public static void main(String[] args) {MyArrayList<b> arrayList = new MyArrayList<>();Test(arrayList);}public static void Test(MyArrayList<? extends a> arrayList) {} } class a {} class b extends a {} class c extends a {}
- <? suoer E>:固定下邊界的通配符,接受指定類及其父類類型(或接口)的數據。