一、 Introduction
Java泛型是java se 1.5的新特性,泛型的本质是参数化类型,指所操作的数据类型被指定为一个参数。泛型可以在类、接口和方法中创建,分别称为泛型类、泛型接口、泛型方法。使用泛型的好处是安全简单,可以将运行时错误提前到编译时错误。
二、 集合中使用泛型
List中使用泛型
public voidtest1(){
List<String> l=new ArrayList();
l.add("看看");
l.add("浏览");
//l.add(12);
for(Iterator i=l.iterator();i.hasNext();){
System.out.println(((String)i.next()).length());
}
}
Set中使用泛型
创建自定义类
public class User {
private String name;
private intage;
public String getName() {
return name;
}
public voidsetName(String name){
this.name = name;
}
public intgetAge() {
return age;
}
public voidsetAge(intage){
this.age = age;
}
public User(String name,intage){
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age="+ age+ "]";
}
}
创建自定义比较器
public class MyCom implements Comparator<User>{
public int compare(User o1,User o2) {
int i=o1.getAge()-o2.getAge();
return i;
}
}
使用带泛型的TreeSet保存自定义对象
public voidtest2(){
TreeSet<User> t=new TreeSet<User>(new MyCom());
t.add(newUser("看看",123));
t.add(newUser("看看",13));
t.add(newUser("看看",133));
t.add(newUser("看看",12));
System.out.println(t);
}
三、 泛型类
如果定义一个类时,使用了泛型,这个类就是泛型类。
例子1:创建一个泛型类
public class Tool1<T> {
//当使用这个类对象的时候,给什么类型,这个T就是什么类型。
private T t;
public voidadd(T t){
this.t=t;
}
public T get(){
return this.t;
}
}
实例化这个类的时候给定泛型
public voidtest3(){
Tool1<String> t=new Tool1<String>();
t.add("看看");
//t.add(13);
System.out.println(t.get().length());
}
注意:不能在类的静态方法中使用泛型类的泛型,因为泛型类的泛型在实例化时确定,而静态方法的加载先于实例化。
例子2:创建一个带多个泛型的泛型类
创建泛型类
public class Tool2<T,X,Y> {
//当使用这个类对象的时候,给什么类型,这个T就是什么类型。
public voidshow(T t,X x,Y y){
System.out.println(t);
System.out.println(x);
System.out.println(y);
}
/* public static void show(T t){
System.out.println(t);
}
不能在泛型类的静态方法中使用泛型类的泛型
*/
}
使用泛型类
public voidtest4(){
Tool2<Integer,String,Double> t=newTool2<Integer,String,Double>();
t.show(1, "会话", 1.2);
}
四、 方法泛型
创建类,设置方法泛型
public class Tool3{
public<M> voidshow(M m){
System.out.println(m);
}
//静态方法可以使用泛型中的方法
public static<P> voidfunc(P p){
System.out.println(p);
}
}
使用泛型方法
public voidtest5(){
Tool3 t=new Tool3();
t.show(14);
Tool3.func("kk");
}
五、 泛型接口
当一个类实现一个接口的时候,可以在实现这个接口的时候指定接口的具体类型,这个接口就是泛型接口。如果指定了具体的数据类型,这个实现类就不是一个泛型类。
创建一个类实现接口,指定这个接口的类型。如果一个类在实现一个泛型接口的时候,没有指定接口的具体类型,那么这个类本身也是一个泛型类。泛型的类型需要在实例化这个类的时候确定。如果一个类去实现或者继承一个接口,就会把泛型也继承下来,这称为泛型的传递。
实现接口时指定具体类型的例子:
public class MyCom2 implements Comparator<String>{
public intcompare(String o1,String o2) {
return 0;
}
}
实例化泛型接口的实现类
public voidtest6(){
MyCom2 my=new MyCom2();
System.out.println(my.toString());
}
实现接口时不指定具体类型的例子:
public class MyCom3<T> implements Comparator<T>{
public intcompare(T o1, T o2) {
return 0;
}
}
实例化实现类的时候确定泛型的类型
public voidtest61(){
MyCom3<String> my=newMyCom3<String>();
System.out.println(my.toString());
}
六、 泛型的通配符
如果不清楚泛型的具体类型是什么的时候,可以使用通配符,写法是一个一个?。如<?>。
public voidtest7(){
List<User> l1=new ArrayList<User>();
l1.add(newUser("hh",13));
l1.add(newUser("h2h",153));
l1.add(newUser("h4h",143));
test(l1);
List<String> l2=newArrayList<String>();
l2.add("ll");
l2.add("浏览");
l2.add("看看");
test(l2);
}
public void test(List<?> l){
for(Iterator<?> i=l.iterator();i.hasNext();){
System.out.println(i.next());
}
}
通配符的上限,使用关键字extends,只能接受extends后的类的或者这个类的子类。
通配符的下限,使用关键字super,只能接受super后面的类的或者这个类的父类。
通配符上下限的例子:
public voidtest8(){
List<sun> l1=new ArrayList<sun>();
List<zi> l2=new ArrayList<zi>();
List<fu> l3=new ArrayList<fu>();
testExtends(l1);
testSuper(l3);
//testExtends(l3);
//testSuper(l1);
}
//通配符的上限
public voidtestExtends(Collection<? extends zi> c){
}
//通配符的下限
public voidtestSuper(Collection<? super zi> c){
}
class fu{}
class zi extendsfu{}
class sun extendszi{}