JDK1.5以后出现的机制,用以解决安全性问题
泛型出现的原因
泛型的特点
- 提高了程序的安全性
- 将运行期遇到的问题转移到了编译期
- 省去了类型强转的麻烦
- 泛型类的出现优化了程序设计
泛型出现的好处
- 将运行时期出现问题ClassCastException,转移到了编译时期,方便于程序员解决问题。让运行时问题减少,提高了安全性
- 避免了强制转换麻烦
泛型的书写格式
泛型格式:
通过<>
来定义要操作的引用数据类型
e.g.
ArrayList<String> al = new ArrayList<String>();
Iterator<String> it = al.iterator();
import java.util.*;
/*
按照字符串长度排序
*/
class Test {
public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<String>(new LenComparator());
ts.add("abcd");
ts.add("cc");
ts.add("cba");
ts.add("aaa");
ts.add("z");
Iterator<String> it = ts.iterator();
while(it.hasNext()) {
String s = it.next();
System.out.println(it.next());
}
}
}
class LenComparator implements Comparator<String> {
public int compare(String o1,String o2) {
int num = new Integer(o1.length()).compareTo(new Integer(o2.length()));
if(num == 0)
return o1.compareTo(o2);
return num;
}
}
自定义泛型类
早期定义Object来完成扩展
泛型前做法:定义类的时候使用Object,使用的时候强转
这样的这发存在问题:在使用的时候,类型转换异常在编译时后不会报错,在运行时候报错
class Student{}.
class Worker{}
class Tool {
private Object obj;
public void setObject(Object obj) {
this.obj = obj;
}
public Object getObject() {
return obj;
}
}
class Test {
public static void main(String[] args) {
Tool t = new Tool();
t.setObject(new Student());
Worker w = (Worker)t.getObject(); //运行时报类型转换异常
}
}
现在定义泛型来完成扩展
当类中要操作的引用数据类型不确定的时候,使用泛型
此时如果出现类型转换异常,就会在编译时候报错
class Student{}.
class Worker{}
class Utils<T> {
private T t;
public void setT(T t) {
this.t = t;
}
public T getT() {
return t;
}
}
class Test {
public static void main(String[] args) {
Utils<Worker> u = new Utils<Worker>();
u.setObject(new Student());
Worker w = u.getObject(); //编译时报类型转换异常
}
}
自定义泛型方法
- 泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了
- 为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上
- 静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上
- 方法上的泛型说明放在返回值修饰符前面
类上定义泛型:相同符号代表相同类型
class Demo<T> {
public void show(T t){
System.out.println("show:"+t);
}
}
方法中定义泛型
class Demo<T> {
public <T> void show(T t) {
System.out.println("show:" + t);
}
public <Q> void print(Q q) {
System.out.println("print:" + q);
}
}
类和方法中可以同时定义
class Demo<T> {
public void show(T t) {
System.out.println("show:" + t);
}
public <T> void print(T t)
{
System.out.println("print:" + t);
}
}
静态方法定义泛型
class Demo<T> {
public void show(T t) {
System.out.println("show:" + t);
}
public <Q> void print(Q q) {
System.out.println("print:" + q);
}
public static <W> void method(W w) {
System.out.println("method:" + w);
}
}
自定义泛型接口
可以在接口子类中指明类型,也可以不指明
interface Inter<T> {
void show(T t);
}
class InterImpl1 implements Inter<String> {
public void show(String t) {
System.out.println("show :" + t);
}
}
class InterImpl2<T> implements Inter<T> {
public void show(T t) {
System.out.println("show :" + t);
}
}
class Test {
public static void main(String[] args) {
InterImpl1 i1 = new InterImpl1();
i1.show("test");
InterImpl2<Integer> i2 = new InterImpl2<Integer>();
i2.show(0);
}
}
通配符(?)
在泛型的使用中,有可能存在多种类型的使用,此时可以用<?>
占位,代表接受任意类型
使用<?>
无法接收参数
public static void printColl(ArrayList<?> al){
Iterator<?> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
使用<T>
可以接收参数
public static <T> void printColl(ArrayList<T> al){
Iterator<T> it = al.iterator();
while(it.hasNext()){
T t = it.next();
System.out.println(t);
}
}
泛型的限定:
? extends E: 可以接收E类型或者E的子类型。上限
? super E: 可以接收E类型或者E的父类型。下限
import java.util.*;
class Person {
private String name;
Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Student extends Person {
Student(String name) {
super(name);
}
}
class Test {
public static void main(String[] args) {
ArrayList<Person> al = new ArrayList<Person>();
al.add(new Person("abc1"));
al.add(new Person("abc2"));
al.add(new Person("abc3"));
printColl(al);
ArrayList<Student> al1 = new ArrayList<Student>();
al1.add(new Student("abc--1"));
al1.add(new Student("abc--2"));
al1.add(new Student("abc--3"));
printColl(al1);
}
public static void printColl(Collection<? extends Person> al){ //接收Person及其子类
Iterator<? extends Person> it = al.iterator();
while(it.hasNext()) {
System.out.println(it.next().getName());
}
}
}