1.类的泛型
class Person<T> {
//泛型作为一个参数(使用的时候有些像类,但不是类)
private String name;
private int age;
private T t;
public Person(String name, int age, T t) {
this.name = name;
this.age = age;
this.t = t;
}
//有自己的get,set
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
测试类中使用: 建议实例化时候指明泛型的类型
public static void main(String[] args) {
//1.初始化时,没有指明类的泛型类型,则认为是Ojbect类(这样和不加泛型直接定义Object一样了)
Person person = new Person("Jack", 21, "Runner");
person.setT(12);
//2.建议在实例化的时候指明泛型的类型
Person<String> person1 = new Person<>("Jack", 12, "Runner");
//person1.setT(12);//编译错误,只能添加String类型,类型更加安全了
}
2.子类继承父类泛型情况
1.class Student extends Person<String>{} 子类继承父类的时候,指明了泛型,子类实例化的时候不需要,指明泛型,(其实子类不是泛型类);
2.class Student<T> extends Person<T>{} 子类继承父类的时候,没有指明泛型的类型,子类实例化的时候,泛型默认Object类,需要再次指明泛型
3.泛型类型不同的引用不能相互赋值
ArrayList<Integer> list1 = null;
ArrayList<String>list2 = null;
list1 = list2;//编译错误
4.泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但是不等同Object;
经验: 要使用泛型,一路使用,要不使用,一路都不要使用。
5.静态方法中不能使用类的泛型。
类的泛型是随着对象创建指定的类型,而静态方法早于对象的创建
public static void test( T t){//形参报错
print(t);//报错
}
6.异常类不能是泛型的
7.泛型方法: 泛型方法中泛型参数,与类的泛型参数没有任何关系。
泛型方法与类是不是泛型类没有关系。
举个栗子:
public <E> List<E> copyArraytoList(E[] arr) {
ArrayList<E> list= new ArrayList<>();
for (E e : arr) {
list.add(e);
}
return list;
}
@Test
public void testMethod(){
Integer[] arr = new Integer[]{1, 3, 5, 3, 23, 54};
List<Integer> list = copyArraytoList(arr);
System.out.println(list);//[1, 3, 5, 3, 23, 54]
}
8. 泛型方法可以是静态的static
public static <E> List<E> copyArraytoList(E[] arr) {}
泛型方法的泛型参数是在调用的时候指定的,不论是类的调用还是对象的调用都是一样。
9.通配符
9.1通配符,代表未知类型,代表不关心或无法确定实际操作的类型,一般与容器类配合使用。
9.2<? extends T>,定义上限,期间只有阅读能力。这种方法表明参数化的类型可能是指定的类型或子类型。
9.3<? super T>,下限定义,有阅读能力和部分写作能力,子类可以写入父类。这种方法表明参数化的类型可以是指定的类型,也可以是父类。
@Test
public void test1(){
List<Object> list2 = null;
List<Integer>list1 = null;
//相当于把 list<?> 看作是父类
List<?> list = null;
list = list1;
list = list2;
}
注意:List<?>list ; 不能往list添加元素,可以添加null。(不能写入数据)
可以读取list中数据,读取的数据类型为Object。
public void print(List<?> list) {
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()) {
//Object 表示最高的父类,所以能用Object接收
Object obj = iterator.next();
System.out.println(obj);
}
}
举个栗子:
G<? extends A> 可以看作是 G<A> 及其G<A>所有子类
G<? super A> 可以看作是 G<A> 及其G<A>所有父类
List<? extends Person>list =null;
List<? super Person> list1 = null;
List<Object>list2 = null;
List<Person> list3 = null;
List<Student >list4 = null;
list = list2;//报错
list = list3;
list = list4;
list1 = list2;
list1 = list3;
list1 = list4;//报错
G<? extends A> 可以看作是 G<A> 及其G<A>所有子类
G<? super A> 可以看作是 G<A> 及其G<A>所有父类