为什么数组协变但是泛型不变? [英] Why are arrays covariant but generics are invariant?

查看:90
本文介绍了为什么数组协变但是泛型不变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从有效的Java由约书亚·布洛克,

From Effective Java by Joshua Bloch,


  1. 阵列从泛型类型在两个重要方面有所不同。首先数组是协变的。泛型是不变的。

  2. 协变仅仅意味着如果X为Y的亚型然后X []也将是子类型Y []的。数组是协变的为String是Object的亚型所以

  1. Arrays differ from generic type in two important ways. First arrays are covariant. Generics are invariant.
  2. Covariant simply means if X is subtype of Y then X[] will also be sub type of Y[]. Arrays are covariant As string is subtype of Object So

的String []是Object的子类型[]

不变只是意味着不管的Y X是亚型与否,

Invariant simply means irrespective of X being subtype of Y or not ,

 List<X> will not be subType of List<Y>.


我的问题是,为什么决定把阵列协在Java中?还有其他的SO职位,如为什么阵列不变,但列出协变?,但他们似乎对斯卡拉要集中,我不能够按照

My question is why the decision to make arrays covariant in Java? There are other SO posts such as Why are Arrays invariant, but Lists covariant?, but they seem to be focussed on Scala and I am not able to follow.

推荐答案

通过<一个href=\"http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Covariant_arrays_in_Java_and_C.23\">wikipedia:

Java和C#的早期版本中不包括仿制药(又名参数多态)。

Early versions of Java and C# did not include generics (a.k.a. parametric polymorphism).

在这样的设置,使得阵列不变规则出有用的多态性的程序。
  例如,考虑写一个函数洗牌数组,或测试使用的元素是Object.equals 法平等的两个阵列的功能。实现不依赖于确切的类型存储在数组中的元素,所以应该可以编写上所有类型的阵列工作的单一功能。这是很容易实现的类型的功能

In such a setting, making arrays invariant rules out useful polymorphic programs. For example, consider writing a function to shuffle an array, or a function that tests two arrays for equality using the Object.equals method on the elements. The implementation does not depend on the exact type of element stored in the array, so it should be possible to write a single function that works on all types of arrays. It is easy to implement functions of type

boolean equalArrays (Object[] a1, Object[] a2);
void shuffleArray(Object[] a);


  
  

然而,如果数组类型分别为不变的处理,也只是有可能调用完全类型的数组这些功能的对象[] 。没有人能,例如,洗牌字符串数组。

However, if array types were treated as invariant, it would only be possible to call these functions on an array of exactly the type Object[]. One could not, for example, shuffle an array of strings.

因此​​,Java和C#的享受数组类型协变。例如,在C#的String [] [对象] ,并在Java中的String [] 是的亚型对象[]

Therefore, both Java and C# treat array types covariantly. For instance, in C# string[] is a subtype of object[], and in Java String[] is a subtype of Object[].

这回答了这个问题:为什么数组协变?,或者更准确地说,为什么的的阵列制成协的的时间的?

This answers the question "Why are arrays covariant?", or more accurately, "Why were arrays made covariant at the time?"

在仿制药进行了介绍,他们故意没有作出协变的原因在此答案由乔恩斯基特指出:

When generics were introduced, they were purposefully not made covariant for reasons pointed out in this answer by Jon Skeet:

没有,一个列表&LT;狗&GT; 不是列表&LT;动物&GT; 。想想你可以用列表与LT做什么;动物&GT; - 你可以任何动物添加到它......包括一只猫。现在,你可以在逻辑上猫添加到小狗的垃圾?绝对不是。

No, a List<Dog> is not a List<Animal>. Consider what you can do with a List<Animal> - you can add any animal to it... including a cat. Now, can you logically add a cat to a litter of puppies? Absolutely not.

// Illegal code - because otherwise life would be Bad
List<Dog> dogs = new List<Dog>();
List<Animal> animals = dogs; // Awooga awooga
animals.add(new Cat());
Dog dog = dogs.get(0); // This should be safe, right?


  
  

突然,你有一个的非常的糊涂猫。

制作阵列的原始动机维基百科的文章中描述的协变并不适用于仿制药,因为通配符发协方差(和逆变)可能的前pression,例如:

The original motivation for making arrays covariant described in the wikipedia article didn't apply to generics because wildcards made the expression of covariance (and contravariance) possible, for example:

boolean equalLists(List<?> l1, List<?> l2);
void shuffleList(List<?> l);

这篇关于为什么数组协变但是泛型不变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆