读书人

敬请牛人指点关于泛型的2个有关问题

发布时间: 2012-12-20 09:53:21 作者: rapoo

敬请牛人指点,关于泛型的2个问题
一直在看泛型,一直感觉困惑极多,先问两个问题,
List<Integer> li=new ArrayList<Integer>();
List<Number> ln=new ArrayList<Number>();
ln=li;
说是编译错误...我想问问
1、为什么会出现错误,java5 是怎么处理 这个的?
2、我们通常的多态实现,如下面代码
class A(){};

class a extends A{}
class b extends B{}

class c
{
A aa=new a();//或 aa=new b();
doMethod()
{
aa.xxx();//假设 xxx()是一个类A的方法,a和b都进行了实现
}

}
要是照 泛型的这个规定,以后这样的代码是不是就不能用了?!!!

还有一个就是
List<?> ls=new ArrayList<String>();
ls.add(new String("A"));
编译也会出错,说是 ? 是 通配符 ,不确定里面是什么值,所以不能往里面传入具体值
这是什么逻辑?不是已经初始化为new ArrayList<String>()了吗?

请大牛们指点指点迷津,谢谢!!!!!

[最优解释]

Java的泛型,做的是“编译时的类型检查”。

1、为什么会出现错误,java5 是怎么处理 这个的?

即使 类型 B 是 类型A 的子类型,那么 List<B> 和 List<A> 也没什么关系,List<B> 也不是 List<A> 的子类型,两种不同的泛型类型赋值就会报错。


还有一个就是
List<?> ls=new ArrayList<String>();
ls.add(new String("A"));
编译也会出错,说是 ? 是 通配符 ,不确定里面是什么值,所以不能往里面传入具体值
这是什么逻辑?不是已经初始化为new ArrayList<String>()了吗?

关键词是“编译”,编译当然会出错,因为 ls 声明的类型是 List<?> , 编译器只能看到声明的类型。


[其他解释]

引用:
raistlic对第二个问题的解释,我觉得明白了一些,但是对第一个问题的解释,我还是不很清楚,我总觉得范型的使用会破坏多态性!!!这是我的个人理解....希望大牛们答疑解惑,谢谢


第一个问题,一个 List<Integer> 类型的对象不能赋值给 List<Number> ln 变量,可以看成是 Java 的泛型规范,如果这条规范被打破的话,泛型的“类型检查”也就出现了漏洞:


// 如果下面这一句能通过编译的话
List<Number> ln = new ArrayList<Integer>();

// ln 声明的类型是 List<Number> , 那么任何 Number 类型都应该能安全的加进去
ln.add(Double.valueOf("1.0")); // runtime exception


泛型变量本身并不继承它们的引用类型的继承关系,这个特性叫做 "invariant",它的反义词是 "covariant",事实上,数组就是 covariant,比如说, String 是 Object 的子类型,所以 String[] 也是 Object[] 的子类型。

所以数组并不能提供可靠的编译时类型检查,其类型检查是在运行时完成的,如果出现问题,它抛出一个运行时异常:


Number[] numbers = new Integer[10];
numbers[0] = Double.valueOf("1.0"); // runtime exception

[其他解释]
你说如果 Animal a = new Animal();VS Cat c = new Cat();
a == c么?
还有你的最后一个问题:
List<?> l 表示l 可以存放 Object 及其 Object 下面的类,那不是和泛型的性能违背了么?
泛型的引入是为了让我们在编译的时候能确定存入集合中的类型,所以返回的时候不用因为要“强制类型转换”而失去 Generic 的功能。
要不你用泛型还有什么意义哈
[其他解释]
差不多就是1楼那个说法了,楼主对这些概念有时候没必要钻牛角尖,在实际应用中用了几次之后就会慢慢的懂了。
[其他解释]
List<Integer> li=new ArrayList<Integer>();
List<Number> ln=new ArrayList<Number>();
ln=li;

li跟ln所容纳的元素类型是不一样的,所以会报错

可能你会认为Integer是Number的子类,所以可以将List<Integer>转成List<Number>
其实是错误的.





[其他解释]
一楼说有点意思!
[其他解释]
raistlic对第二个问题的解释,我觉得明白了一些,但是对第一个问题的解释,我还是不很清楚,我总觉得范型的使用会破坏多态性!!!这是我的个人理解....希望大牛们答疑解惑,谢谢
[其他解释]
List<Integer> li=new ArrayList<Integer>();
List<Number> ln=new ArrayList<Number>();
ln=li;
说是编译错误...我想问问
ln和li的类型不一样,泛型就是可以简单理解为不需类型转换,要不你的li取出值时,由于不知是什么类型必须先转换为Integer型。
[其他解释]
还望大牛们指点 指点
[其他解释]
第一个这样不就可以了
List<Integer> li=new ArrayList<Integer>();
List<? extends Number> ln=new ArrayList<Number>();//Number的子类包含Integer类
ln=li;
第二个是因为?是通配符,表示object,而你传了一个String类作为成员,当然会报错
[其他解释]

引用:
Java的泛型,做的是“编译时的类型检查”。

1、为什么会出现错误,java5 是怎么处理 这个的?

即使 类型 B 是 类型A 的子类型,那么 List<B> 和 List<A> 也没什么关系,List<B> 也不是 List<A> 的子类型,两种不同的泛型类型赋值就会报错。


还有一个就是
List<?> ls=new ArrayList<String>();
ls.a……



List<?> ls=new ArrayList<String>();
ls.add(new String("A"));


楼主这个ls是?类型的,也就是Object的,哪有.add()这个方法,肯定就报错了。

[其他解释]
引用:
差不多就是1楼那个说法了,楼主对这些概念有时候没必要钻牛角尖,在实际应用中用了几次之后就会慢慢的懂了。
泛型通配符<?>一般用在参数里面吗
[其他解释]
谢谢大家的参与,结帖了

读书人网 >J2SE开发

热点推荐