泛型的理解和好处
看一个需求
- 请编写程序,在ArrayList 中,添加3个Dog对象
- Dog对象含有name 和 age,并输出name 和 age (要求使用getXxx0)
先使用传统的方法来解决 ->引出泛型
class Dog {
public String name;
public int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString {return "Dog [name=" + name + ", age=" + age + "]";
创建3个Dog对象,放入集合中,用foreach遍历这个集合。
即for(Object obj : arrayList){}
里面,需要将obj向下转型为Dog,才能拿到Dog的名字和年龄。
如果此时不小心往ArrayList添加了一个Cat对象。那么上面这个foreach遍历就会报错。
使用传统方法的问题分析
- 不能对加入到集合 ArrayList中的数据类型进行约束(不安全)
- 遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响
针对第一点可以指定ArrayList只接受Dog对象
ArrayList<Dog> arrayList = new ArrayList<Dog>();
还有一个好处就是可以直接在foreach里面进行类型转化for(Dog dog : arrayList)
看菜鸟编程
泛型的声明
interface <T> {}
和class<K,V>{}
泛型的实例化
List<String> strList = new ArrayList<String> ();
Iterator<Customer> iterator = customers.iterator();
泛型的应用
集合的源码
泛型的使用细节
- 泛型接收的类型只能是引用类型,不能是基本数据类型int float
- 在给泛型指定具体类型后,可以传入该类型或者其子类类型
- 泛型的使用形式
ArrayList<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
在实际中,往往写成
ArrayList<Integer> list3 = new ArrayList<>();
List<Integer> ist4 = new ArrayList<>():
- 如果是这样写 泛型默认是 object
ArrayList arrayList = new ArrayList()
练习
创建3个Employee对象,存在Arraylist里面,用list的sort方法排序,要求先按名称排序,同名则按年龄排序。
class Employee{
private String name;
private int sal;
private MyDate birthday;
}
class MyDate{
private int year;
private int month;
private int day;
}
通过传入匿名内部类实现compare方法来进行排序。首先比较名字,再比较年龄。年龄的比较我封装成了一个方法,员工类直接调用就行。
list.sort(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
if (o1.getName().compareTo(o2.getName())!=0){
return o2.getName().compareTo(o1.getName());
}
return o2.compare(o1);
}
});
public int compare(Employee e){
if (this.getBirthday().getYear() != e.getBirthday().getYear()){
return this.getBirthday().getYear() > e.getBirthday().getYear()? -1:1;
}
if (this.getBirthday().getMonth() != e.getBirthday().getMonth()){
return this.getBirthday().getYear() > e.getBirthday().getYear()? -1:1;
}
if (this.getBirthday().getDay() != e.getBirthday().getDay()){
return this.getBirthday().getYear() > e.getBirthday().getYear()? -1:1;
}
return 0;
}
老师写法,将MyDate类实现Comparable接口,重写compare方法。
自定义泛型
基本语法
class 类名 <T,R...>{
成员
}
细节
- 普通成员可以使用泛型(属性、方法)
- 使用泛型的数组,不能初始化(不知道开辟多大空间)
- 静态方法中不能使用类的泛型(因为静态是和类相关的,在类加载时,对象还没有创建,如果静态方法\属性使用了泛型,JVM无法初始化)
- 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
- 如果在创建对象时,没有指定类型,默认为Object