泛型:jdk1.5以后出现的安全机制。
好处:
1、将运行时的ClasscastException转到了运行时期。
2、避免了强制转换的麻烦。
一、将运行时的ClassCastException赚到了运行时期:
在没有添加泛型的程序中会出现很多的小黄点,以提示程序员存在安全隐患。
程序运行到第29行时报错Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String。这是因为前面加入的是 "abc" 字符串,取出的时候需要将add( )方法里面添加的object 类型的" abc "转化为String类型。而后来加入的Integer(4)是整数类型的,整数不能转化为String类型,会发生异常。这时我们需要强制程序不能添加 其他类型的元素,就出现了“泛型” 。
加入泛型以后的程序:
添加了泛型以后,元素添加的类型被指定了,其他类型的元素不能被添加进来。将运行时才能发现的异常转到了编译时期。也无需再对数据进行强制类型转换。
二、泛型的示例
<> 尖括号什么时候用?
当将要操作的引用数据类型不确定的时候就使用<>。 将要操的 引用数据类型传入即可。其实<>就是一个接受引用数据类型的参数范围。
在程序中只要用到了<>和接口就要明确传入的数据类型引用。
泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。
泛型的擦除:
运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。
为什么会擦除呢?
类在运行的时候首先会被类加载器加载检查。而这类加载器是JDk1.4的, 泛型是JDK1.5以后出现的新特性,所以在加载的时候会擦除。加载完成以后系统会自动进行补偿。泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者在强制转换了。
三、在集合中的应用。
先写一个Person bean
package cn.itcast.p2.bean;
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public int compareTo(Person p){
// Person p = (Person)obj;
int temp = this.age - p.age;
return temp==0?this.name.compareTo(p.name):temp;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person:"+getName()+":"+getAge();
}
}
编写一个比较器,主要条件根据名字排序,次要条件根据年龄排序
package cn.itcast.p3.comparator;
import java.util.Comparator;
import cn.itcast.p2.bean.Person;
/*编写一个比较器,主要条件根据名字排序,次要条件根据年龄排序*/
public class ComparatorByName 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;
}
}
创建对象,将比较器作为参数传递。
package cn.itcast.p1.generic.demo;
import java.util.Iterator;
import java.util.TreeSet;
import cn.itcast.p2.bean.Person;
import cn.itcast.p3.comparator.ComparatorByName;
public class GenericDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
TreeSet<Person> ts = new TreeSet<Person>(new ComparatorByName());
ts.add(new Person("lisi8",21));
ts.add(new Person("lisi3",23));
ts.add(new Person("lisi",21));
ts.add(new Person("lis0",20));
Iterator<Person> it = ts.iterator();
while(it.hasNext()){
Person p = it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
}
根据姓名和年龄排序的结果出来: