目录
1.泛型的理解(约束了类型)
2.泛型的介绍、语法
3.自定义泛型类
1.基本语法
4.自定义泛型方法
5.自定义泛型接口
6.泛型的继承和通配符
(1)编译时,检查了添加元素的类型,提高了安全性
例:
ArrayList<Dog> arrayList = new ArrayList<Dog>(); //存放的是Dog类的,说明只能添加这种类型的数据
不能添加其他类型的数据,否则会报错
arrayList.add(new Dog("小黄",5)); //T
arrayList.add(new Cat("招财猫", 8)); //F
(2)减少了类型转换的次数,提高效率
例:在使用迭代器时,先声明泛型,就不用向下转换类型
(1)< > 尖括号内只能放引用类型,不能是基本数据类型(int long double float byte char short)
(2)在类声明或实例化时只要指定好需要的具体类型即可
Person <String>person = new Person<String>("cc"); //此时E的类型是String
Person<E>是一个泛型类,当我在做上面的操作是,指定了E的类型是String,所以下面类中有关E的部分全是替换成String的类型
(3)泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型
class Person<E> { E s ;//E 表示 s 的数据类型, 该数据类型在定义 Person 对象的时候指定,即在编译期间,就确定 E 是什么类型 public Person(E s) {//E 也可以是参数类型 this.s = s; } public E f() {//返回类型使用 E return s; } public void show() { System.out.println(s.getClass());//显示 s 的运行类型
(4)若 Person person = new Person(“”); 默认给它的泛型就是 Object
class 类名<T,R...>{
成员
}
class Tiger<T, R, M> { String name; R r; //属性使用到泛型 M m; T t; //因为数组在 new 不能确定 T 的类型,就无法在内存开空间 T[] ts; public Tiger(String name) { this.name = name; } public Tiger(R r, M m, T t) {//构造器使用泛型 this.r = r; this.m = m; this.t = t; } public Tiger(String name, R r, M m, T t) {//构造器使用泛型 this.name = name; this.r = r; this.m = m; this.t = t; } //因为静态是和类相关的,在类加载时,对象还没有创建 //所以,如果静态方法和静态属性使用了泛型,JVM 就无法完成初始化 // static R r2; 错的 // public static void m1(M m) { 错的 } public String getName() { return name; } public void setName(String name) { this.name = name; } public R getR() { return r; } public void setR(R r) {//方法使用到泛型 this.r = r; } public M getM() {//返回类型可以使用泛型. return m; } public void setM(M m) { this.m = m; } public T getT() { return t; } public void setT(T t) { this.t = t; } public String toString() { return "Tiger{" + "name='" + name + '\'' + ", r=" + r + ", m=" + m + ", t=" + t + ", ts=" + Arrays.toString(ts) + '}'; } }
注意:
(1)普通成员也可以使用泛型(属性,方法)
(2)使用泛型的数组不能初始化(因为泛型的类型不确定,类型确定是类声明或者实例化的时候才确定的)
(3)静态方法(属性)中不能使用类的泛型(因为,静态与类相关的,类加载的时候,对象还没创建,JVM无法完成初始化)
(4)泛型类的类型,是创建对象的时候才确定的!!!(解释了第2.3条)
class Fish <T,R>{ //泛型类 }
注意:
当泛型方法被调用时,类型才会确定!!!
(1)泛型方法:例:public<U,M> void eat(U u, M m) { //泛型要在前面出现过,否则会报错 }
(2)使用泛型:例:public void setR(R r) { } //方法使用泛型
(3)泛型方法使用类的泛型:
public<K> void hello(R r, K k) { } R为类的泛型
//泛型方法,可以使用类声明的泛型,也可以使用自己声明泛型
interface 接口名<T,R...> { }
注意:
1.接口中,静态成员不能使用泛型
//U name; 不能这样使用
2.泛型接口的类型,在继承接口或者实现接口的时候才确定
interface IUsb <U,R> { }
例:class BB implements IUsb< Integer,Float >
3.没有指定类型,默认是Object
interface IUsb<U,R>{ R get(U u); void hi(R r); void run(R r1,U u1); //U name 不能这样用 }
(1)泛型不具备继承性
指的是: List<Object> list = new ArrayList<String>() 错的!!!
(2)<?>:支持任意泛型类型
(3)<? extends A>:支持A类以及A类的子类,规定了泛型的上限
(4)<? super A?>:支持A类以及A类的父类,规定了泛型的下限