一、泛型
1、起因
JDK1.4以前类型不明确
1)装入集合的类型都被当做Object对待,从而失去自己的实际类型。
2)从集合中取出来时往往需要转型,效率低,容易产生错误。
2、解决办法:
1)在定义容器的时候同时定义容器中对象的类型
2)可以在定义Collection的时候指定
3)也可以在循环时用Iterator指定
3、好处
增加程序的可读性和稳定性
4、举例
1)例1
package com.hpe.generic;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
public class TestGeneric {
public static void main(String[] args) {
List<String> c = new ArrayList<String>();
c.add("aaa");
c.add("bbb");
c.add("ccc");
for(int i=0; i<c.size(); i++) {
String s = c.get(i); //返回值是String类型,不再是Object类型
System.out.println(s);
}
Collection<String> c2 = new HashSet<String>();
c2.add("ddd"); c2.add("eee"); c2.add("fff");
Iterator<String> i = c2.iterator(); //指定迭代器中要迭代的对象为String类型
while(i.hasNext()) {
String s2 = i.next(); //无需对返回值做强制类型转换,返回值已指定为String类型
System.out.println(s2);
}
}
}
/**
* Comparable接口允许使用泛型,因此在继承该接口时指定泛型为当前类型,这样
* 在重写compareTo方法时,可以保证在该方法内部要比较的对象与this对象类型相同
* @author fuchs
*
*/
class MyAge implements Comparable<MyAge> {
int age;
@Override
public int compareTo(MyAge ma) {
if(this.age > ma.age) {
return 1;
} else if(this.age < ma.age) {
return -1;
} else return 0;
}
}
运行结果:
aaa
bbb
ccc
eee
ddd
fff
2)之前Map接口时的例子如果使用了自动打包和泛型会很简便(例子中的测试代码有所删减):
package com.hpe.generic;
import java.util.HashMap;
import java.util.Map;
public class TestMapMethod3 {
public static void main(String[] args) {
Map<String, Integer> m1 = new HashMap<String, Integer>();
m1.put("one", new Integer(1));
m1.put("two", new Integer(2));
m1.put("three", new Integer(3));
System.out.println(m1.size());
System.out.println(m1.containsKey("one")); //String类重写了hashCode()方法
if(m1.containsKey("two")) {
//int i = ((Integer)m1.get("two")).intValue();
int i = m1.get("two"); //泛型保证了返回值是Integer类型,自动解包将Integer类型解包为int类型
System.out.println(i);
}
}
}
运行结果:
3
true
2
3)对自动打包和解包时的例子使用泛型:
package com.hpe.generic;
import java.util.HashMap;
import java.util.Map;
public class TestArgsWords3 {
public static void main(String[] args) {
Map<String, Integer> m = new HashMap<String, Integer>();
for(int i=0; i<args.length; i++) {
if(m.get(args[i]) == null) {
m.put(args[i], 1);
} else {
int freq = m.get(args[i]);
m.put(args[i], freq+1);
}
}
System.out.println(m.size() + (m.size() > 1 ? " words" : " word") + " detected;\n" + m);
}
}
运行结果:
5 words detected;
{aaa=3, ee=1, ccc=2, bbb=4, dddd=2}
5、总结
1)以后使用到容器时尽量使用泛型,增强程序的可读性和稳定性。
2)程序的可读性增强:当我们在往容器中放对象时候,要放什么类型对象进去、要拿什么类型的对象出来一目了然,
3)程序的稳定性增强:从容器中取出对象的时候,不用对容器中的对象进行强制类型转换了,而如果类型转换错了,在运行期间才能发现,尽量要将运行期间出的错误提前到编译期间来,如果有了泛型约束容器中的类型,在编译期间就能得知是否有类型转换错误。