Java泛型
为什么需要泛型?
1.编译的时候就会进行类型检查,保证类型安全。
2.无需强转,避免类型转换异常。
定义泛型类:
public class Order<T> { T order; }
如果定义了泛型类,实例化的时候没有指明类的泛型,则默认泛型类为Object。
public class SubOrder extend Order<Integer> { }
如果父类有泛型,子类可以保留父类的泛型,也可以不保留(如上)
定义泛型方法:
<T> T[] toArray(T[] a);
在方法中出现泛型结构,其中T与所在类的泛型参数没关系
什么时候用到泛型类?例子:
public class DAO<T> { # 使用泛型方便对不同类型的数据进行操作 public void add(T t) {//通用的数据库操作方法
}
public T get(int index) {
}
... } public class Student extend DAO<Student> { } public class Customer extend DAO<Customer> { }
为什么要通配符?
因为类A是类B的父类,G<A>和G<B>是没有关系的,而二者的共同的父类是:G<?>
所以:public void test() {
List<Object> list1 = null; List<String> list2 = null; list1 = list2; # 会报错 List<?> list = null; list = list1; # 没问题 list = list2; # 没问题
List<String> list3 = new ArrayList<>();
list3.add("abc");
list3.add("cde");
list = list3; # 没问题
list.add("fgh"); # 编译不通过,不能往list里面add除null之外的元素
Object o = list.get(0); # 没问题,前提是o为Object对象
} public void test2(List<Object> list) { #这个方法不能传List<String等其它类型>的参数 } public void test2(List<?> list) { #这个方法能传List<各种类型>的参数 }
有限制条件的通配符的使用
public class Student extend Person(){ } List<? extends Person> list1 = null; #相当于(负无穷,Person] List<? super Person> list2 = null;#相当于[Person,正无穷) List<Student> list3 = null; List<Person> list4 = null; List<Object> list5 = null; list1 = list3; # List<? extends Person>可以做List<Student>的父类 list1 = list4; # List<? extends Person>可以做List<Person>的父类 list1 = list5; # 出错 list2 = list3; # 报错 list2 = list4; # List<? super Person>可以做List<Person>的父类 list2 = list5; # List<? super Person>可以做List<Object>的父类
list4 = new ArrayList<>();
list1 = list4;
Person p = list1.get(0);# 没问题
Student s = list1.get(0); #报错
list2 = list4;
Object o = list2.get(0); # 没问题
总结
1.jdk 5.0新增的特性。
2.在实例化集合类时,可以指明具体的泛型类型。
3.泛型的数据类型必须是类,不能是基本数据类型。
4.如果实例化是没有指明泛型的类型,默认类型为java.lang.Object类型。
5.静态方法中不能使用类的泛型,因为静态方法可以再泛型未指定前被调用
6.泛型方法可以声明为静态的。