所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如继承或实现接口,用这个类型声明变量、创建对象时)确定(既传入实际的类型参数,也称为类型实参)。
JDK1.5改写了集合框架中的全部接口和类,为这些接口、类增加了泛型支持,从而可以在声明集合变量、创建集合对象时传入类型参数。(List
如果没有指定泛型的类型,默认类型为java.lang.Object类型。
ArrayList list=new ArrayList();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add("awsl"); //类型不安全
for (Object object : list) {
int number = (int) object; //异常
System.out.println(number);
}
ArrayList<Integer> list=new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
for (int number : list) {
System.out.println(number);
}
Map<String, Integer> map=new HashMap<String, Integer>();
map.put("Tom", 10);
map.put("Jerry", 20);
map.put("Mark", 30);
//泛型嵌套
Set<Map.Entry<String, Integer>> entry=map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator=entry.iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> e=iterator.next();
String key=e.getKey();
int number=e.getValue();
System.out.println(key+": "+number);
}
public class Study {
static class Pair<T>{
private T first;
private T second;
public Pair() { this.first=null; this.second=null; }
public Pair(T first,T second) { this.first=first; this.second=second; }
public T getFirst() { return first; }
public T getSecond() { return second; }
public void setFirst(T first) { this.first = first; }
public void setSecond(T second) { this.second = second; }
}
public static Pair<String> minmax(String[] a) {
if(a==null||a.length==0) return null;
String min=a[0];
String max=a[0];
for(int i=1;i<a.length;i++) {
if(min.compareTo(a[i])>0) min=a[i];
if(max.compareTo(a[i])<0) max=a[i];
}
return new Pair<>(min,max);
}
public static void main(String[] args) {
String[] word= {"Mary","had","a","little","lamb"};
Pair<String> mm=minmax(word);
System.out.println("min= "+mm.getFirst());
System.out.println("max= "+mm.getSecond());
}
}
运行结果:
min= Mary
max= little
当子类在继承带泛型的父类时,由于父类指定了泛型类型,则实例化子类对象时,子类不需要在声明泛型。
public class Sub extends Parent<Integer>{}
Sub sub=new Sub();
但是子类也可以定义为泛型:
public class Sub<T> extends Parent<T>{}
Sub<String> sub=new Sub<>();
泛型方法可以定义在普通类中,也可以定义在泛型类中(泛型方法的泛型参数与类的泛型参数没有任何关系)。
注意:public T getFirst() { return first; } 这些不是泛型方法。
public class Test<T>{
public <E> List<E> copyFromArrayToList(E[] array) { //注意返回值前面有一个类型参数
ArrayList<E> list = new ArrayList<E>();
for(E e : array) {
list.add(e);
}
return list;
}
public static void main(String[] args) {
Test<String> test=new Test<>();
Integer[] array = new Integer[] {1,2,3,4};
List<Integer> list = test.copyFromArrayToList(array);
System.out.println(list);
}
}
运行结果:[1, 2, 3, 4]
泛型方法可以声明为 static 静态的,原因:泛型参数是在调用方法时确定的,并非在实例化类时确定的。
有时,类或方法需要对类型变量加以约束,可以通过对类型变量E设置限定(bound)实现这一点:public
假如我们需要对数据库进行操作,那么我们有一个DAO类来存放数据库的基本的增删改查操作。
public class DAO<T> {
//添加一条记录
public void add(T t) {...}
//删除一条记录
public boolean remove(T t) {...}
//修改一条记录
public void update(int index,T t) {...}
//查询一条记录
public T search(int index) {...}
}
同时,我们有一个客户类Customer
public class Customer {
String name;
int number;
public Customer () { this.name=null; this.number=null; }
public Customer (String name,int number) { this.name=name; this.number=number; }
public String getName() { return name; }
public int getNumber() { return number; }
public void setName(String name) { this.name= name; }
public void setNumber(int number) { this.number= number; }
}
我们还有一个专门对客户表进行操作的类
public class CustomerDAO extends DAO<Customer> {...}
现在,我们可以在其他地方对客户表操作
public class Test {
CustomerDAO dao = new CustomerDAO();
dao.add(new Cumstomer());
List<Customer> list = dao.search(10);
}
如果类A是类B的父类,G 和 G 二者不具备子父类关系,二者是并列关系。
Object object = null;
String stirng = null;
object = string; //正确
List<Object> list1 = null;
List<String> list2 = null;
list1 = list2; //错误
相反,如果类A是类B的父类,A
List<String> list1 = null;
ArrayList<String> list2 = null;
list1 = list2; //子父类关系
无边界的通配符的主要作用就是让泛型能够接受未知类型的数据。
public class Test<T>{
public static void print(List<?> list) {
//对于List>不能添加数据(除了null)
//Object是类的父类,并且不会报错
for (Object object : list) {
System.out.print(object);
}
}
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(new Integer[] {1,2,3,4});
List<String> list2 = Arrays.asList(new String[] {"Tom","Jerry","Marry","Tong"});
System.out.println(list1);
System.out.println(list2);
}
}
在类型参数中使用 extends 表示这个泛型中的参数必须是 E 或者 E 的子类。
G extends A> 可以作为 G 和G的父类,其中B是A的子类 。
在类型参数中使用 super 表示这个泛型中的参数必须是 E 或者 E 的父类。
G super A> 可以作为 G 和G的父类,其中B是A的父类 。