有人告诉我,Java允许协变数组子类型化,换句话说,如果A是B的子类型,那么A []是B
[]的子类型,但这是一个不好的功能,因为它可能导致运行时错误。有人可以给我一个具体的例子来说明它如何导致运行时错误,以及Java是否/如何解决此问题?
谢谢!
很简单。
String strings[] = {"Broken","Type", "system"};
Object objects[] = strings;
objects[0] = 5; // compiles fine, but throws ArrayStoreException at runtime
只要您将内容取出,协变类型就不错,但是放入内容的那一刻,整个事情就破裂了。假设您有一个采用Object []作为参数的方法。
fn(Object[]a){
...
}
能用调用它不是很好String[]
吗?
String[] s = {"I","didn't","know","that","this","was","broken"}
fn(s);
好吧,听起来很自然,尤其是在我们没有通用语言的早期。只要没有任何突变,所有这些都可以正常工作,并且Java不提供任何机制来保证这一点。
你应该总是青睐Lists
过arrays
,因为Lists
使用generics
它是不变的。
问题内容: 我了解协方差和逆方差。但是有一件小事我无法理解。在Coursera的“ Scala中的函数式编程”课程中,Martin Ordersky提到: 函数的参数类型是互变的,而返回类型是协变的 因此,例如在Java中,让extends出现。并让一个函数为: 我有函数调用为 所以基本上就是这样。根据Wiki,协方差是“从宽到窄转换”。在上面,我们正在从狗变成动物。所以论点类型不是协变而是协变吗
本文向大家介绍Java中数组协变和范型不变性踩坑记录,包括了Java中数组协变和范型不变性踩坑记录的使用技巧和注意事项,需要的朋友参考一下 前言 变性是OOP语言不变的大坑,Java的数组协变就是其中的一口老坑。因为最近踩到了,便做一个记录。顺便也提一下范型的变性。 解释数组协变之前,先明确三个相关的概念,协变、不变和逆变。 下面话不多说了,来一起看看详细的介绍吧 一、协变、不变、逆变 假设,我为
问题内容: 摘自Joshua Bloch的Effective Java, 数组在两个重要方面不同于通用类型。第一数组是协变的。泛型是不变的。 协变量仅表示如果X是Y的子类型,则X []也将是Y []的子类型。数组是协变的,因为字符串是Object的子类型,所以 不变式仅表示X是否为Y的子类型, 问题答案: Java和C#的早期版本不包含泛型(又称参数多态性)。 在这种情况下,使数组不变会排除有用的
问题内容: 这行代码给出以下警告: 警告:变量sh只能在此位置为null。 并且,此代码给出以下警告: 警告:局部变量sh可能尚未初始化。 问题答案: 这是因为您需要初始化数组。试试这个: 如果不初始化,则会收到这些警告,如果运行它也会得到警告。
问题内容: 这是我阅读的一篇有关scala中的协方差和协方差的文章的代码片段。但是,我无法理解由scala编译器引发的错误消息“错误:协变类型A出现在值pet2的类型A的协变位置中 我对此代码段的理解是Pets是协变的,并且接受属于A的子类型的对象。但是,add函数仅接受类型为A的参数。成为协变意味着Pets可以采用Type A及其子类型的参数。那么这怎么会引发错误。矛盾的问题甚至从何而来。 对以
问题内容: 有没有Java原始数组的不变选择?制作一个原始数组final实际上并不能阻止人们做类似的事情 我希望数组的元素不可更改。 问题答案: 不适用于原始数组。你将需要使用列表或其他数据结构: