引言
第一段代码
importjava.util.ArrayList;
importjava.util.List;
publicclass fanxingmain {
publicstaticvoid main(String[] args) {
//TODO Auto-generated method stub
Listlist = new ArrayList();
list.add("qqyumidi");
list.add("corn");
list.add(100);
for(int i = 0; i <list.size(); i++) {
String name = (String) list.get(i);// 1
System.out.println("name:" + name);
}
}
}
执行结果如下
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at we.main(we.java:18)
定义了一个List类型的集合-动态数组,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型
第一段主要存在两个问题:
1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。
2.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。
第二段代码
public class fanxingmain {
publicstatic void main(String[] args) {
//TODO Auto-generated method stub
List<String> list = newArrayList<String>();
list.add("qqyumidi");
list.add("corn");
list.add(100); //1
for (int i = 0; i < list.size();i++) {
String name = list.get(i); // 2
System.out.println("name:"+ name);
}
}
}}
执行结果如下:
Exception in thread "main"java.lang.Error: Unresolved compilation problem:
Themethod add(int, String) in the type List<String> is not applicable forthe arguments (int)
atfanxingmain.main(fanxingmain.java:16)
采用泛型写法后,在//1处想加入一个Integer类型的对象时会出现编译错误,通过List<String>,直接限定了list集合中只能含有String类型的元素,
从而在//2处无须进行强制类型转换,因为此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。
注意:没有泛型数组一说…..
JAVA泛型思想
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为、泛型接口、泛型方法。引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的,而这种转换是要求开发者对类型可以预知的情况下进行的。对于强制类型转换错误的情况,可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
使用泛型与不使用泛型比对
使用泛型例子
classGen<T> {
private T ob; // 定义泛型成员变量
public Gen(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public void showType() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
publicclass GenDemo {
public static void main(String[] args) {
// 定义泛型类Gen的一个Integer版本
Gen<Integer> intOb = newGen<Integer>(88);
intOb.showType();
int i = intOb.getOb();
System.out.println("value= "+ i);
System.out.println("----------------------------------");
// 定义泛型类Gen的一个String版本
Gen<String> strOb = newGen<String>("Hello Gen!");
strOb.showType();
String s = strOb.getOb();
System.out.println("value= "+ s);
}
}
没有使用泛型
class Gen2 {
private Object ob; // 定义一个通用类型成员
public Gen2(Object ob) {
this.ob = ob;
}
public Object getOb() {
return ob;
}
public void setOb(Object ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo2 {
public static void main(String[] args) {
// 定义类Gen2的一个Integer版本
Gen2 intOb = new Gen2(new Integer(88));
intOb.showTyep();
int i = (Integer) intOb.getOb();
System.out.println("value= " + i);
System.out.println("---------------------------------");
// 定义类Gen2的一个String版本
Gen2 strOb = new Gen2("Hello Gen!");
strOb.showTyep();
String s = (String) strOb.getOb();
System.out.println("value= " + s);
泛型在重构中的应用
原始代码
public class StringFoo {
private String x;
public StringFoo(String x) {
this.x = x;
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
public class DoubleFoo {
private Double x;
public DoubleFoo(Double x) {
this.x = x;
}
public Double getX() {
return x;
}
public void setX(Double x) {
this.x = x;
}
}
Java 5之前重构
| 4 5 6 7 8 9 10 11 12 13 14 15 | public class ObjectFoo { private Object x; public ObjectFoo(Object x) { this.x = x; } public Object getX() { return x; } public void setX(Object x) { this.x = x; } } |
| 1 2 3 4 5 6 7 8 9 10 | public class ObjectFooDemo { public static void main(String args[]) { ObjectFoo strFoo = new ObjectFoo(new String("Hello Generics!")); ObjectFoo douFoo = new ObjectFoo(new Double(new Double("33"))); ObjectFoo objFoo = new ObjectFoo(new Object()); System.out.println("strFoo.getX=" + (String) strFoo.getX()); System.out.println("douFoo.getX=" + (Double) douFoo.getX()); System.out.println("objFoo.getX=" + objFoo.getX()); } |
Java 5之后泛型重构
| 11 12 13 14 15 16 17 18 19 20 21 22 | class GenericsFoo<T> { private T x; public GenericsFoo(T x) { this.x = x; } public T getX() { return x; } public void setX(T x) { this.x = x; } } public class GenericsFooDemo { public static void main(String args[]) { GenericsFoo<String> strFoo = new GenericsFoo<String>("Hello Generics!"); GenericsFoo<Double> douFoo = new GenericsFoo<Double>(new Double("33")); GenericsFoo<Object> objFoo = new GenericsFoo<Object>(new Object()); System.out.println("strFoo.getX=" + strFoo.getX()); System.out.println("douFoo.getX=" + douFoo.getX()); System.out.println("objFoo.getX=" + objFoo.getX()); } } |
java泛型通配符泛型
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class CollectionGenFooDemo { public static void main(String args[]) { //CollectionGenFoo<ArrayList> listFoo = null; //listFoo = new CollectionGenFoo<ArrayList>(new ArrayList()); CollectionGenFoo<?> listFoo1 = null; listFoo1=new CollectionGenFoo<ArrayList>(new ArrayList()); System.out.println("实例化成功!"); } } |
注意:
1、如果只指定了<?>,而没有extends,则默认是允许Object及其下的任何Java类了。也就是任意类。
2、泛型不单可以向上,如<? extends Collection>,还可以向下,如<?super Double>,表示类型只能接受Double及其上层父类类型,如Number、Object类型的实例。
3、定义可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。这些都与泛型类中泛型的使用规则类似。