泛型
泛型是JDK1.5中一个最重要的特征。通过引入泛型,我们将获得编译时类型的安全和运行时更小地抛出ClassCastExceptions的可能。
ClassCastExceptions(类型转换异常)
我们来举一个小例子:
package fiftyThird;
import java.util.List;
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("string");
list.add(new Integer(2));
list.add(new Boolean(false));
String string = (String)list.get(0);
Integer integer = (Integer)list.get(1);
String b = (String)list.get(2);
}
}
结果是:
Exception in thread “main” java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.String at fiftyThird.ArrayListTest.main(ArrayListTest.java:17)
看代码,我们知道第三个赋给list的类型是boolean但是我们提取的时候给强转成String所以会抛出异常ClassCastException,因为boolean不能转换为String。
在JDK1.5中,你可以声明一个集合将接收/返回的对象的类型
package fiftyThird;
public class BooleanFoo {
private Boolean foo;
public Boolean getFoo() {
return foo;
}
public void setFoo(Boolean foo) {
this.foo = foo;
}
}
package fiftyThird;
public class IntegerFoo {
private Integer foo;
public Integer getFoo() {
return foo;
}
public void setFoo(Integer foo) {
this.foo = foo;
}
}
类别定义时的逻辑完全一样,只是里面成员变量的类型不同.
如果需要多个相似的类,需要定义多个文件,不同的只是变量的类别,而逻辑是完全一样的.
对之前代码的一些改写
package fiftyThird;
public class ObjectFoo {
private Object foo;
public Object getFoo() {
return foo;
}
public void setFoo(Object foo) {
this.foo = foo;
}
public static void main(String[] args) {
ObjectFoo foo1 = new ObjectFoo();
ObjectFoo foo2 = new ObjectFoo();
foo1.setFoo(new Boolean(false));
foo2.setFoo(new Integer(10));
Boolean b = (Boolean)foo1.getFoo();
Integer i = (Integer)foo2.getFoo();
}
}
上述代码只能在运行的时候发现是什么类型的,而当我们加入泛型后:
package fiftyThird;
public class GenericFoo<T> {
private T foo;
public T getFoo() {
return foo;
}
public void setFoo(T foo) {
this.foo = foo;
}
public static void main(String[] args) {
GenericFoo<Boolean> foo1 = new GenericFoo<Boolean>();
GenericFoo<Integer> foo2 = new GenericFoo<Integer>();
foo1.setFoo(new Boolean(false));
foo2.setFoo(new Integer(3));
Boolean boolean1 = foo1.getFoo();
Integer integer = foo2.getFoo();
System.out.println(boolean1);
System.out.println(integer);
}
}
我们在编译期间就能发现问题,这里面就是泛型。
在泛型命名时我们一般以单个大写字母表示。
所谓泛型就是变量类型参数化。
foo1 = foo2;
这样就是错误的。
GenericFoo aFoo = new GenericFoo();
当我们定义好泛型后不适用会提示警告:
GenericFoo 是原始类型。应该将对通用类型 GenericFoo 的引用参数化
aFoo.setFoo("hello");
String string = (String)aFoo.getFoo();
System.out.println(string);
结果是:
hello
Generic多个泛型实现
package fiftyFourth;
public class Generic<T1,T2> {
private T1 foo1;
private T2 foo2;
public T1 getFoo1() {
return foo1;
}
public void setFoo1(T1 foo1) {
this.foo1 = foo1;
}
public T2 getFoo2() {
return foo2;
}
public void setFoo2(T2 foo2) {
this.foo2 = foo2;
}
public static void main(String[] args) {
Generic<Integer, Boolean> foo = new Generic<Integer,Boolean>();
foo.setFoo1(new Integer(-20));
foo.setFoo2(new Boolean(false));
System.out.println(foo.getFoo1());
System.out.println(foo.getFoo2());
}
}
结果是:
-20
false
数组的泛型
package fiftyFourth;
public class Generic2<T>{
private T[] fooArray;
public T[] getFooArray() {
return fooArray;
}
public void setFooArray(T[] fooArray) {
this.fooArray = fooArray;
}
public static void main(String[] args) {
Generic2<String> foo = new Generic2<String>();
String[] str1 = {"hello", "world", "welcome"};
String[] str2 = null;
foo.setFooArray(str1);
str2 = foo.getFooArray();
for(int i = 0 ; i < str2.length ; i++) {
System.out.println(str2[i]);
}
}
}
结果是:
hello
world
welcome
集合的泛型
自己模仿集合做一个类似的类
package fiftyFourth;
public class SimpleCollection<T> {
private Object[] objArr;
private int index = 0;
public SimpleCollection() {
objArr = new Object[10];
}
public SimpleCollection(int capacity) {
objArr = new Object[capacity];
}
public void add(T t) {
objArr[index++] = t;
}
public int getLength() {
return this.index;
}
public T get(int i) {
return ((T)objArr[i]);
}
public static void main(String[] args) {
SimpleCollection<Integer> collection = new SimpleCollection<Integer>();
for(int i = 0; i < 10; i++) {
collection.add(new Integer(i));
}
for(int i = 0; i < 10 ; i++) {
Integer integer = collection.get(i);
System.out.println(integer);
}
}
}
结果是:
0
1
2
3
4
5
6
7
8
9
泛型的泛型
package fiftyFourth;
public class WrapperFoo<T>{
private GenericFoo3<T> foo;
public GenericFoo3<T> getFoo() {
return foo;
}
public void setFoo(GenericFoo3<T> foo) {
this.foo = foo;
}
public static void main(String[] args) {
GenericFoo3<Integer> foo3 = new GenericFoo3<Integer>();
foo3.setFoo(new Integer(-10));
WrapperFoo<Integer> wrapperFoo = new WrapperFoo<Integer>();
wrapperFoo.setFoo(foo3);
GenericFoo3<Integer> genericFoo3 = wrapperFoo.getFoo();
System.out.println(genericFoo3.getFoo());
}
}
class GenericFoo3<T>{
private T foo;
public T getFoo() {
return foo;
}
public void setFoo(T foo) {
this.foo = foo;
}
}
结果是:
-10