https://www.bilibili.com/video/BV1Kb411W75N
所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)。
例如,Arraylist,当不指定泛型时可以传入任意类型的值,但我们想固定它里面装的数据的类型,就可以使用泛型:ArrayList<Integer> list = new ArrayList<Integer>();
,这里的<Integer>就是泛型。泛型是jdk5.0新增的特性。
import java.util.*; public class GenericTest { public static void main(String[] args) { GenericTest genericTest = new GenericTest(); genericTest.test3(); } // 在集合中使用泛型之前的情况: public void test1() { ArrayList list = new ArrayList(); // 需求:存放学生的成绩 list.add(78); list.add(76); list.add(89); list.add(88); // 问题一:类型不安全 // list.add("Tom"); for (Object score : list) { // 问题二:强转时,可能出现ClassCastException int stuScore = (int) score; System.out.println(stuScore); } } // 在集合中使用泛型的情况:以ArrayList为例 public void test2() { ArrayList<Integer> list = new ArrayList<Integer>(); list.add(78); list.add(87); list.add(99); list.add(65); // 编译时就会进行类型检查,保证数据的安全 // list.add("Tom"); // 方式一: // for (Integer score : list) { // // 避免了强转操作 // int stuScore = score; // // System.out.println(stuScore); // } // 方式二: Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { int stuScore = iterator.next(); System.out.println(stuScore); } } }
总结:
定义泛型类:public class Order<T>
定义泛型接口:public interface aa<T>
定义完泛型类和泛型接口后,其内部结构就可以使用相应的泛型。
注意点:
泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。
泛型方法和所属的类是不是泛型类也没有关系
泛型方法可以声明为静态。原因:泛型参数是在调用方法时确定的,并非在实例化类时确定。
声明泛型方法举例:
public static <E> List<E> copyFromArrayToList(E[] arr) { ArrayList<E> list = new ArrayList<>(); for (E e : arr) { list.add(e); } return list; }
若A是B的父类:
G<A>和G<B>二者没有子父类关系,是并列关系。
A<G>和B<G>是子父类关系,A<G>是B<G>的父类。
若A是B的父类,G<A>和G<B>二者共同的父类是G<?>(通配符)。
使用通配符后的集合无法写入数据,只能写入null。可读取数据,但读取出来的数据类型是Object。
<? extends Person>: ≤ Person 类
<? super Person>: ≥ Person 类