一、泛型的好处:
泛型是jdk1.5出现的安全机制。将运行时期的问题ClassCastException转到了编译时期。避免了强制转换的麻烦。
二、<>:什么时候用?
当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可。其实<>就是一个用于接收具体引用数据类型的参数范围。
三、注意:
在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。
四、泛型的擦除:
运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。
为什么擦除呢?因为为了兼容运行的类加载器。
题: ArrayList<Integer> list = new ArrayList<Integer>();
在这个泛型为Integer的ArrayList中存放一个String类型的对象。
这里就要用到泛型的擦除。
代码:
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Demo {
public static void main(String[] args)
throws ReflectiveOperationException, ReflectiveOperationException {
// TODO 自动生成的方法存根
ArrayList<Integer> list = new ArrayList<Integer>();
String str="asf";
Class clazz=list.getClass();
Object obj=clazz.newInstance();
Method method=clazz.getDeclaredMethod("add",Object.class);
method.invoke(list, str);
System.out.println(list.get(0));
System.out.println(Float.MIN_VALUE);
}
}
五、泛型的补偿
泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者在强制转换了。
六、泛型的限定
? extends E: 接收E类型或者E的子类型对象。上限一般存储对象的时候用比如添加元素 addAll。
代码:
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Person(){}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public class Student extends Person{
private String name;
private int age;
public Student(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class Student extends Person{
private String name;
private int age;
public Student(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
ArrayList<Person> al1 = new ArrayList<Person>();
al1.add(new Person("abc",30));
al1.add(new Person("abc4",34));
ArrayList<Student> al2 = new ArrayList<Student>();
al2.add(new Student("stu1",11));
al2.add(new Student("stu2",22));
ArrayList<Worker> al3 = new ArrayList<Worker>();
al3.add(new Worker("worker",11));
al3.add(new Worker("worer",22));
ArrayList<String> al4 = new ArrayList<String>();
al4.add("abcdeef");
//al1.addAll(al4);//错误,类型不匹配。
al1.addAll(al2);
al1.addAll(al3);
System.out.println(al1.size());
}
}
// 一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的。不会出现类型安全隐患。
class MyCollection<E>{
public void add(E e){
}
public void addAll(MyCollection<? extends E> e){
}
}
结果:6
? super E: 接收E类型或者E的父类型对象。 下限。一般取出对象的时候用。比如比较器。
代码:
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class Demo1 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
TreeSet<Person> al1 = new TreeSet<Person>(new CompByName());
al1.add(new Person("abc4",34));
al1.add(new Person("abc1",30));
al1.add(new Person("abc2",38));
TreeSet<Student> al2 = new TreeSet<Student>(new CompByName());
al2.add(new Student("stu1",11));
al2.add(new Student("stu7",20));
al2.add(new Student("stu2",22));
TreeSet<Worker> al3 = new TreeSet<Worker>(new CompByWorkerName());
al3.add(new Worker("woker1",11));
al3.add(new Worker("worker2",22));
TreeSet<String> al4 = new TreeSet<String>();
al4.add("abcdeef");
Iterator<Student> it = al2.iterator();
while(it.hasNext()){
System.out.println(it.next().getAge());
}
}
}
class CompByName implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp==0? o1.getAge()-o2.getAge():temp;
}
}
class CompByStuName implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp==0? o1.getAge()-o2.getAge():temp;
}
}
class CompByWorkerName implements Comparator<Worker>{
@Override
public int compare(Worker o1, Worker o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp==0? o1.getAge()-o2.getAge():temp;
}
}
结果:11
22
20