泛型实质上就是程序员定义安全的类型。
一、回顾“向上转型”与“向下转型”
向上转型是安全的,
* 但是执行“向下转型”操作时用错了类型或者并没执行该操作:
* 并不存在语法错误,可以被编译器接受,但执行时会出现 java.lang.ClassCastException
package day22;
public class reviewupdown {
public static void main(String[] args) {
/*回归向上转型、向下转型*/
T m = new T();
/*向上转型*/
m.setB(new Boolean(true));
System.out.println(m.getB());
/*向下转型*/
m.setB(new Float(12.3));
Float f = (Float) m.getB();
System.out.println(f);
/*“向上转型是安全的,
* 但是执行“向下转型”操作时用错了类型或者并没执行该操作:
* 并不存在语法错误,可以被编译器接受,但执行时会出现 java.lang.ClassCastException”*/
m.setB(new Float(11.4));
Integer i = (Integer) m.getB();
System.out.print(i);
}
}
class T{
private Object B;
public Object getB() {
return B;
}
public void setB(Object b) {
B = b;
}
}
运行结果:
true
12.3
Exception in thread "main" java.lang.ClassCastException: java.lang.Float cannot be cast to java.lang.Integer
at day22.reviewupdown.main(reviewupdown.java:20)
二、定义泛型类
1、在JDK1.5版本后,提出泛型
格式:
类名<T>
T:代表一个类型的名称。
2、代码案例
package day22;
public class GenericTest {
public static void main(String[] args) {
OverClass<Float> f = new OverClass<Float>(); //实例化一个Float对象
OverClass<Integer> c = new OverClass<Integer>();//实例化一个Integer对象
f.setOver(11.6f);
c.setOver(7);
Float f2 = f.getOver();//不需要类型转换
Integer c2 = c.getOver();//不需要类型转换
System.out.println(f2);
System.out.println(c2);
}
}
class OverClass<T>{ //定义泛型类
private T over; //定义泛型成员变量
public T getOver() {//设置getXXX()方法
return over;
}
public void setOver(T over) { //设置setXXX()方法
this.over = over;
}
}
运行结果:
11.6
7
解析:
在类名后添加了一个<T>语句,使用了泛型机制。
可以将OverClass称为泛型类,同时返回和接受的参数使用T这个类型。
三、泛型的常规用法
1、定义泛型类时,可以声明多个类型
语法:
MutiOverClass<T1,T2>
MutiOverClass:类型名称
这样在实例化指定类型的对象时就可以指定多个类型。
2、定义泛型类时声明数组类型
代码案例:
package day22;
public class GenericTest {
public static void main(String[] args) {
/*定义泛型类时声明数组类型*/
ArrayClass<Integer> arr = new ArrayClass<Integer>();
Integer m[] = {1,2,3,4,5};
arr.setTt(m);
for(int i = 0;i < arr.getTt().length;i++) {
System.out.print(arr.getTt()[i]);
System.out.print(" ");
}
}
}
class ArrayClass<T> {
private T[] tt; //定义泛型数组
public T[] getTt() { //获取成员数组
return tt;
}
public void setTt(T[] tt) { //设置setXXX()为成员数组赋值
this.tt = tt;
}
}
运行结果:
1 2 3 4 5
三、集合类声明容器的元素
这些集合框架已经被泛型化,可以直接使用。
四、泛型的高级用法
4.1 限制泛型可用类型
默认可以使用任何类型来实例化一个泛型类对象,但是Java中也对泛型类实例的类型作了限制。
语法:
class 类名称<T extends anyClass>
其中, anyClass为类或接口
代码案例:
package day22;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
public class LimitClass <T extends List>{
public static void main(String[] args){
/*可以实例化实现List接口的类*/
LimitClass<ArrayList> l1 = new LimitClass<ArrayList>();
LimitClass<LinkedList> l2 = new LimitClass<LinkedList>();
/*这句是不对的,因为HashMap没实现List()接口
LimitClass<HashMap> l3 = new LimitClass<HashMap>();*/
}
}
解析:
将泛型作了限制,设置泛型类型必须实现List接口。
4.2 使用类型通配符
1.在泛型机制中,提供了类型通配符,
其主要作用是:
在创建一个泛型类对象时限制这个泛型类的类型实现或继承某个接口或类的子类。
声明这样的对象可以使用“?”来表示,同时依然使用extends关键字来对泛型加以限制。
2.格式:
泛型类名称<? extends List> a = null;
<? extends List>表示类型未知,当需要使用该泛型对象时,可以单独实例化。
如:
A<? extends List> a = null;
a = new A<ArrayList>();
a = new A<LinkedList>();
3.在泛型中使用通牌符形式
List<String> l1 = new List<String>();//实例化一个ArrayList对象
l1.add("aaa");//在集合中添加字符
List<?> l2 = l1;//使用通配符
List<?> l3 = new LinkedList<Integer>();
System.out.println(l2.get(0));//获取集合中的第一个值
注意:
这l1 和 l2的区别使用通配符声明的名称实例化的对象不能对其进行加入新的值,只能获取或删除。
4.3继承泛型类与实现泛型接口
4.3.1 在项目中创建一个类文件,在该类中继承泛型类
public class ExtendClass<T1>{
//..}
class SubClass<T2,T3> extends ExtendClass<T1>{
//..}
注意:
需要指明ExtendClass<T1>;
如果Exte会ndClass,则T1,T2,T3都会自动变成Object。
所以在一般情况下都将父类的泛型类型保留。
4.3.2定义的泛型接口也可以被实现,implements
泛型总结:
1.泛型的类型参数只能是类类型
2.泛型的类型个数可以是多个
3.可以使用extends关键字限制泛型的类型
4.可以使用通配符限制泛型的类型
星期一, 十一月 23, 2015 22:53:52