您的位置:首页 > 编程语言 > Java开发

JAVASE之泛型

2015-01-21 21:05 162 查看
泛型:JDK1.5版本以后出现新特性,用于解决安全问题,是一个类型安全机制

eg:ArrayList<String> al = new ArrayList<String>();

集合加上泛型后,该集合只能存储String类型的值,若存储其他类型的值,在编译时期将报错

好处:

    1、将运行时期出现问题ClassCastException,转移到了编译时期

    方便于程序员解决问题,让运行时期问题减少,安全

    2、避免了强制转换麻烦

    

通俗点看:其实 <> 就是用来接收类型的,当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

泛型出现前后的做法:

class Worker
{
...
}
//泛型前做法
class Tool
{
private Object  obj;
public void setObject(Object obj)
{
this.obj = obj;
}
public Object getObject()
{
return obj;
}
}
//什么时候定义泛型类
//当类中要操作的引用数据类型不确定的时候,基本数据类型不确定定义不了
//早期定义Object来完成扩展,因为Object是祖宗
class Utils
{
private QQ q;
public void setObject(QQ q)
{
this.q = q;
}
public QQ getObject()
{
return q;
}
}

class GenericDemo3
{
public static void main(String[] args)
{
Utils u = new Utils();

u.setObject(new Worker();)

Worker w = u.getObject();

}
}


 

泛型类定义的泛型,在整个类中有效,如果被方法使用
那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了

class Demo
{
public void show(T t)
{
System.out.println("show:"+t);
}
public void print(T t)
{
System.out.println("print:"+t);
}
}


为了让不同方法可以操作不同类型,而且类型不确定

可以将泛型定义在方法上

特殊方法:
静态方法不可以访问类上定义的泛型-
--------只有对象才能带着类型去运行,静态比对象先加载
如果静态方法操作的引用数据类型,可以将泛型定义在方法上

演示:
class Demo//也可以定义在接口上,用法和类一样
{
public void show(T t)
{
System.out.println("show:"+t);
}
public  void print(Q q)  //Q就相当于形参,可以是任意的
{
System.out.println("print:"+q);
}
public static  void method(W t)
{
System.out.println("method:"+t);
}
}

class GenericDemo4
{
public static void main(String[] args)
{
Demo d = new Demo();
d.print(9);//自动装箱类型,将其转换为Integer
d.show("shdk");//失败,当new对象时不加泛型则正确

//由于泛型定义在方法上,所以下面两条语句都正确
d.print(5);
d.print("sfd");

//静态方法的泛型
Demo.method("hahahhaha");

}
}


泛型限定

? 通配符 也可以理解为占位符

//通配符的意义就是无论是什么泛型都可以打印,Integer和String的都可以打印
public static void printColl(ArrayList<?> al)
{
Iterator<?> it = al.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}


泛型的限定:

? extends E 表示可以接受E类型或者E的子类型,上限

? super E 表示可以接受E类型或者E的父类型 下限

例子:
addAll(Collection<? extends E>comparator)----->添加可以添加E或者E的子类型
TreeSet(Comparator<? super E>comparator)--->比较的时候比较的类型和其父类型都能接受子类对象进来,兼容

import java.util.*;
class GenericDemo6
{
public static void main(String[] args)
{
ArrayList al1 = new ArrayList();
al1.add(new Person("lisi01"));
al1.add(new Person("lisi02"));
al1.add(new Person("lisi03"));

Iterator it = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next().getName());
}
}
public static void printColl(ArrayList<? extends Person> al)
{	/*如果仅仅是Person的话,不能传入Person的子类Student,所以也可以是 ? Super Student,

区别:
若是<? extends Person>,则提供的方法必须是父类的
若是<? Super Student>,调用方法时,还需要进行强转,因为Object也是父类
*/

Iterator<? extends Person> it = al.iterator();
while(it.hasNext())
{
System.out.println(it.next().getName());
}
}

}

class Person
{
private String name;

Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}

}


比较器的泛型限定:

class Person
{
private String name;

Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}

}

class Student extends Person implements Comparable//<? super E>,既可以比较学生,也可以比较学生的父类
{
Student(String name)
{
super(name);
}

public int compareTo(Person s)
{
System.out.println("niininin");
return 1;
}

}

//比较器
class Comp implements Comparator//所以,也可以是Person
{
public int compare(Student s1,Student s2)
{
return s1.getName().compareTo(s2.getName());
}
}

//既能比较Student,也可以比较Student的父类型
TreeSet ts = new TreeSet(new Comp());
ts.add(new Student("abc01"));
ts.add(new Student("cdf03d"));


因为传到比较器时,你传来的是Student,所以比较器上肯定是Student或Student的父类型

也就是说implements Comparable<  > 这里的类型要大于传进来的类型所以是?Super E

当执行ts.add(new Student("abc01"));传进来的是Student类型,所以比较器是Student或者Student的父类型才可以接收,

 

但是,当有两级继承时候 爷--父--孙----implements Comparable<  >这里的参数必须要统一,所以直接整爷爷的类型
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: