泛型
認識泛型
定義類、接口、方法時,同時聲明了一個或者多個類型變量(如:) ,稱為泛型類、泛型接口,泛型方法、它們統稱為泛型。
作用:利用泛型,可以限制集合存儲數據的類型.
泛型的本質:把具體的數據類型作為參數傳給類型變量。
泛型類
類型變量建議用大寫的英文字母,常用的有:E、T、K、V 等
public class ArrayList<E>{. . .
}修飾符 class 類名<類型變量,類型變量,…> { }
- 目標:了解泛型類的定義方式
需求:定義一個MyGenericCls類,要求該類有一個屬性,屬性的類型可以在創建對象時指定
public class MyGenericCls<E>{E name;public void setName(E name) {this.name = name;}public E getName() {return name;}
}
//1.創建對象,將name的類型指定為StringMyGenericCls<String> cls1 = new MyGenericCls<>();cls1.setName("張三");String name1 = cls1.getName();System.out.println(name1);//2.創建對象,將name的類型指定為IntegerMyGenericCls<Integer> cls2 = new MyGenericCls<>();cls2.setName(666);Integer name2 = cls2.getName();System.out.println(name2);//3.泛型類的作用:可以提高一個類中數據類型的靈活性
泛型接口
- 目標:了解泛型接口的定義方式
public interface A<E>{. . .
}
修飾符 interface 接口名<類型變量,類型變量,…> { }
需求:定義一個泛型接口MyGenericInter,并定義實現類實現該接口
public interface MyGenericInter<E> {//接口名后面定義的泛型(類型變量),在整個接口中要使用數據類型的地方都可以用,可以提高一個接口中類型的靈活性void method1(E e);E method2();
}
public class InterImpl1 implements MyGenericInter<String>{@Overridepublic void method1(String s) {}@Overridepublic String method2() {return null;}
}
public class InterImpl2 implements MyGenericInter<Integer>{@Overridepublic void method1(Integer integer) {}@Overridepublic Integer method2() {return null;}
}
泛型方法
- 目標:了解泛型方法的定義方式
public static <T> void test(T t){
}修飾符 <類型變量,類型變量,…> 返回值類型 方法名(形參列表) { }
需求:定義一個泛型方法,可以接收任意類型的引用數據類型數組,將其變成ArrayList集合返回
/*定義方法:數組的類型不確定!需要提高類型的靈活性* 明確參數:數組類型,數組的元素使用泛型變量* 明確返回值:ArrayList集合,集合中存儲的元素和數組元素類型保持一致*/public static <T> ArrayList<T> arrToList(T[] arr) {//2.創建ArrayList集合對象ArrayList<T> list = new ArrayList<T>();//3.遍歷數組for (int i = 0; i < arr.length; i++) {T data = arr[i];list.add(data);}return list;}
Integer[] arr1 = {11,22,33,44,55};
ArrayList<Integer> list1 = arrTolist(arr1);
System.out.println(list1);String[] arr2 = {"物", "羅"};
ArrayList<Integer> list2 = arrTolist(arr2);
System.out.println(list2);//[11, 22, 33, 44, 55]
//[物, 羅]
泛型通配符
通配符:?
可以在“使用泛型”的時候代表不確定的類型
泛型的上下限:
泛型上限: ? extends Car
: ? 能接收的必須是Car或者其子類 。
泛型下限: ? super Car
: ? 能接收的必須是Car或者其父類。
4. 目標:了解泛型通配符的使用方式
需求:優化sellApple和sellBanana兩個方法,變成一個批量銷售所有水果的方法
/*** 水果類*/
public class Fruit {
}//蘋果類
public class Apple extends Fruit{
}//香蕉類
public class Banana extends Fruit{
}
//創建蘋果集合
ArrayList<Apple> apples = new ArrayList<>();
//創建香蕉集合
ArrayList<Banana> bananas = new ArrayList<>();
//public static void sellFruit(ArrayList<?> fruits){//場景:放入集合時,集合中的數據類型不確定,此時使用泛型通配符?,此時?代表一切類型//public static void sellFruit(ArrayList<?> fruits) {//場景:此時還是不確定給泛型變量賦什么類型,依然使用通配符?,不過要限制它的范圍,使用通配符的上限//要求:?要么是水果類型,要么是水果的子類類型public static void sellFruit(ArrayList<? extends Fruit> fruits){System.out.println("銷售水果");}//批量銷售蘋果public static void sellApple(ArrayList<Apple> apples) {System.out.println("銷售蘋果");}//批量銷售香蕉public static void sellBanana(ArrayList<Banana> bananas) {System.out.println("銷售香蕉");}
}
public static void main(String[] args) {//需求:優化sellApple和sellBanana兩個方法,變成一個批量銷售所有水果的方法//創建蘋果集合ArrayList<Apple> apples = new ArrayList<>();//創建香蕉集合ArrayList<Banana> bananas = new ArrayList<>();//銷售蘋果和香蕉//sellApple(apples);//sellBanana(bananas);//sellBanana(apples);//sellApple(bananas);//此時方法的形參類型是ArrayList,所以sellFruit、sellApple、sellBanana三個方法的類型是一樣的!sellFruit(apples);sellFruit(bananas);//創建狗集合,并銷售ArrayList<Dog> dogs = new ArrayList<>();//有些時候,雖然不確定具體是什么類型,但是還是要限制一下類型的范圍,此時需要限制類型是水果!//sellFruit(dogs);}