日期:2014-05-20  浏览次数:20679 次

Java菜鸟诚心请教一个关于泛型的问题
首先定义了Dog类和Cat类,再实例化,Dog dog=new Dog();Cat cat=new Cat();
然后 ,写了这句:Set set=new HashSet<Dog>();
问题来了,这时候如果写set.add(cat);不会报错,而且执行System.out.print(set);后会输出Cat类的哈希码(百度后看到有人说是哈希码,这个不影响此问题)。

这个该怎么理解呢?按照我个人的想法:在这个程序中,通过new创建的HashSet类的对象,它只能存放Dog类型的对象,但是能调用add方法增加Cat类的对象cat。我感觉说不通。

诚心请教。

------解决方案--------------------
其实,这也算一个历史遗留问题,java最开始设计的时候没有支持泛型,是在后来的版本里加上的,为了兼容以前的代码,在运行的时候,这些泛型信息就被丢掉了。你贴出的代码实际上是很危险的,试想如果你执行下面的代码

Set set = new HashSet<Dog>();
set.add(new cat());
for (Object dog : set) {
    Dog d = (Dog)dog;
    ...
}

就会报一个ClassCastException。所以你应该这么写

Set<Dog> set = new HashSet<Dog>();

这样你再添加cat时就会报编译错误,从而快速发现解决问题。
最后顺便说一句,java的泛型实际上并不是彻底的泛型,也算是java设计的一个小败笔吧。
------解决方案--------------------
java 的泛型 不是真正的泛型 只是根据祖先类Object 来实现的 也就是说 List<String> 实质上就是List<Object>  

[转]JAVA的泛型只是一个语法糖,实际上在运行时还是有类型转换的过程,从JVM生成的代码来看,和传递一个Object(或者extends的类型)没什么区别。当然泛型的最大好处是编绎期的类型错误检查。

明白JAVA泛型的大致实现原理之后,看很多泛型代码都比较清晰了:)

和C++的泛型比较,C++的泛型是在编绎期实现的,为每一个类型都生成一份代码,所以C++的泛型容易让编绎后的代码出现膨胀。