所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返 回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、 创建对象时确定(即传入实际的类型参数,也称为类型实参)。
泛型引入的背景JDK1.5之前对于不确定的容器到底存储什么类型的对象,都将其设置为Object类型。
JDK1.5,以后使用泛型来解决这一问题,对于不知道存储什么类型的对象,设计为一个参数,在实例化或者确定为什么类型的时候,再去指明其类型。
子类继承泛型类时可以指明泛型类型。
【SubOrder.java】 public class SubOrder extends Order<Integer> {//SubOrder:不是泛型类 public static <E> List<E> copyFromArrayToList(E[] arr){ ArrayList<E> list = new ArrayList<>(); for(E e : arr){ list.add(e); } return list; } } > //实例化时,如下的代码是错误的 SubOrder<Integer> o = new SubOrder<>();子类继承泛型类的时候也可以不指明具体类型,子类也可以是泛型类。
【SubOrder1.java】 public class SubOrder1<T> extends Order<T> {//SubOrder1<T>:仍然是泛型类 }【DAO.java】:定义了操作数据库中的表的通用操作。 ORM思想(数据库中的表和Java中的类对应)
public class DAO<T> {//表的共性操作的DAO //添加一条记录 public void add(T t){ } //删除一条记录 public boolean remove(int index){ return false; } //修改一条记录 public void update(int index,T t){ } //查询一条记录 public T getIndex(int index){ return null; } //查询多条记录 public List<T> getForList(int index){ return null; } //泛型方法 //举例:获取表中一共有多少条记录?获取最大的员工入职时间? public <E> E getValue(){ return null; } } 【CustomerDAO.java】: public class CustomerDAO extends DAO<Customer>{//只能操作某一个表的DAO } 【StudentDAO.java】: public class StudentDAO extends DAO<Student> {//只能操作某一个表的DAO }当在声明类型变量时,如果不希望这个类型变量代表任意引用数据类型,而是某个系列的引用数据类型,那么可以设定类型变量的上限。
语法格式:
<类型变量 extends 上限>如果有多个上限
<类型变量 extends 上限1 & 上限2>如果多个上限中有类有接口,那么只能有一个类,而且必须写在最左边。接口的话,可以多个。
如果在声明<类型变量>时没有指定上限,默认上限是java.lang.Object。
例如:我们要声明一个两个数求和的工具类,要求两个加数必须是Number数字类型,并且实现Comparable接口。
通配符:?
类A是类B的费用类,G和G是没关系的。
二者的共同父类是G<?>
@Test public void test3(){ List<Object> list1 = null; List<String> list2 = null; List<?> list = null; list = list1; list = list2; //编译通过 // print(list1); // print(list2);G<? extends A> 可以作为G和G的父类,其中B是A的子类
G<? super A> 可以作为G和G的父类,其中B是A的父类
@Test public void test4(){ List<? extends Person> list1 = null; List<? super Person> list2 = null; List<Student> list3 = new ArrayList<Student>(); List<Person> list4 = new ArrayList<Person>(); List<Object> list5 = new ArrayList<Object>(); list1 = list3; list1 = list4; // list1 = list5; // list2 = list3; list2 = list4; list2 = list5; //读取数据: list1 = list3; Person p = list1.get(0); //编译不通过 //Student s = list1.get(0); list2 = list4; Object obj = list2.get(0); 编译不通过 // Person obj = list2.get(0); //写入数据: //编译不通过 // list1.add(new Student()); //编译通过 list2.add(new Person()); list2.add(new Student()); }