目录
1.泛型的理解(约束了类型)
(1)编译时,检查了添加元素的类型,提高了安全性
例:
ArrayList<Dog> arrayList = new ArrayList<Dog>(); //存放的是Dog类的,说明只能添加这种类型的数据
不能添加其他类型的数据,否则会报错
arrayList.add(new Dog("小黄",5)); //T
arrayList.add(new Cat("招财猫", 8)); //F
(2)减少了类型转换的次数,提高效率
例:在使用迭代器时,先声明泛型,就不用向下转换类型
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
3.自定义泛型类
1.基本语法
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>{ //泛型类 }
4.自定义泛型方法
注意:
当泛型方法被调用时,类型才会确定!!!
(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为类的泛型
//泛型方法,可以使用类声明的泛型,也可以使用自己声明泛型
5.自定义泛型接口
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 不能这样用
}
6.泛型的继承和通配符
(1)泛型不具备继承性
指的是: List<Object> list = new ArrayList<String>() 错的!!!
(2)<?>:支持任意泛型类型
(3)<? extends A>:支持A类以及A类的子类,规定了泛型的上限
(4)<? super A?>:支持A类以及A类的父类,规定了泛型的下限