Why are arrays covariant but generics are invariant?java.lang.ArrayStoreException: when assigning value with incorrect type to Object[] arrayWhy is upcasting arrays allowed, while not with generics?What's the differences between Array declaration and Collection declarationGenerics and Subtype problems in JavaWhy does this line not compile List<Object> l = new ArrayList<String>()?Differences between cast arraylist and cast array in javadifferent behavior of array v.s. list<T> in Java for sub-classHow to create List<List<T>> in java?How do I correctly implement methods for objects that implement Comparable in an ArrayList in Java?Passing information from Integer Array and List to parameter with Object Array and ListCreate ArrayList from arrayHow do I check if an array includes an object in JavaScript?How to append something to an array?How do I generate random integers within a specific range in Java?How do I determine whether an array contains a particular value in Java?Loop through an array in JavaScriptHow do I remove a particular element from an array in JavaScript?Why is subtracting these two times (in 1927) giving a strange result?For-each over an array in JavaScript?Why is processing a sorted array faster than processing an unsorted array?
Pre-1972 sci-fi short story or novel: alien(?) tunnel where people try new moves and get destroyed if they're not the correct ones
How to hide an urban landmark?
Watts of filament extrusion
English word for "product of tinkering"
Should I compare a std::string to "string" or "string"s?
Frame failure sudden death?
When conversion from Integer to Single may lose precision
Does Disney no longer produce hand-drawn cartoon films?
Are there any important biographies of nobodies?
What is the reason for double NULL check of pointer for mutex lock
Mobile App Appraisal
How might Southern Ontario becoming a tech powerhouse hurt New York?
How to officially communicate to a non-responsive colleague?
Generate a Graeco-Latin square
At what point in time did Dumbledore ask Snape for this favor?
What is wrong with this proof that symmetric matrices commute?
Understanding a current source topology
Do any instruments not produce overtones?
What do abbreviations in movie scripts stand for?
Share calendar details request from manager's manager
Universal hash functions with homomorphic XOR property
Recommended tools for graphs and charts
Why is one of Madera Municipal's runways labelled with only "R" on both sides?
Converting 0 to NULL in attribute table
Why are arrays covariant but generics are invariant?
java.lang.ArrayStoreException: when assigning value with incorrect type to Object[] arrayWhy is upcasting arrays allowed, while not with generics?What's the differences between Array declaration and Collection declarationGenerics and Subtype problems in JavaWhy does this line not compile List<Object> l = new ArrayList<String>()?Differences between cast arraylist and cast array in javadifferent behavior of array v.s. list<T> in Java for sub-classHow to create List<List<T>> in java?How do I correctly implement methods for objects that implement Comparable in an ArrayList in Java?Passing information from Integer Array and List to parameter with Object Array and ListCreate ArrayList from arrayHow do I check if an array includes an object in JavaScript?How to append something to an array?How do I generate random integers within a specific range in Java?How do I determine whether an array contains a particular value in Java?Loop through an array in JavaScriptHow do I remove a particular element from an array in JavaScript?Why is subtracting these two times (in 1927) giving a strange result?For-each over an array in JavaScript?Why is processing a sorted array faster than processing an unsorted array?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
From Effective Java by Joshua Bloch,
- Arrays differ from generic type in two important ways. First arrays are covariant. Generics are invariant.
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[] is subtype of Object[]Invariant simply means irrespective of X being subtype of Y or not ,
List<X> will not be subType of List<Y>.
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.
java arrays generics language-design covariance
|
show 1 more comment
From Effective Java by Joshua Bloch,
- Arrays differ from generic type in two important ways. First arrays are covariant. Generics are invariant.
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[] is subtype of Object[]Invariant simply means irrespective of X being subtype of Y or not ,
List<X> will not be subType of List<Y>.
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.
java arrays generics language-design covariance
1
Isn't this because generics were added later?
– Sotirios Delimanolis
Sep 6 '13 at 21:18
1
i think comparing between arrays and collections is unfair, Collections use arrays in the background !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:35
2
@EL-conteDe-monteTereBentikh Not all collections, for exampleLinkedList.
– Paul Bellora
Sep 6 '13 at 21:35
@PaulBellora i know that Maps are different than Collection implementers, but i read in the SCPJ6 that Collections generally relied on arrays !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:39
Because there is no ArrayStoreException; when inserting wrong element in Collection where as array has it. So Collection can find this only at retrieval time and that too because of casting. So generics will ensure solving this issue.
– Kanagavelu Sugumar
Jun 8 '16 at 11:18
|
show 1 more comment
From Effective Java by Joshua Bloch,
- Arrays differ from generic type in two important ways. First arrays are covariant. Generics are invariant.
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[] is subtype of Object[]Invariant simply means irrespective of X being subtype of Y or not ,
List<X> will not be subType of List<Y>.
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.
java arrays generics language-design covariance
From Effective Java by Joshua Bloch,
- Arrays differ from generic type in two important ways. First arrays are covariant. Generics are invariant.
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[] is subtype of Object[]Invariant simply means irrespective of X being subtype of Y or not ,
List<X> will not be subType of List<Y>.
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.
java arrays generics language-design covariance
java arrays generics language-design covariance
edited May 23 '17 at 10:31
Community♦
11
11
asked Sep 6 '13 at 21:16
eagertoLearneagertoLearn
3,215195596
3,215195596
1
Isn't this because generics were added later?
– Sotirios Delimanolis
Sep 6 '13 at 21:18
1
i think comparing between arrays and collections is unfair, Collections use arrays in the background !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:35
2
@EL-conteDe-monteTereBentikh Not all collections, for exampleLinkedList.
– Paul Bellora
Sep 6 '13 at 21:35
@PaulBellora i know that Maps are different than Collection implementers, but i read in the SCPJ6 that Collections generally relied on arrays !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:39
Because there is no ArrayStoreException; when inserting wrong element in Collection where as array has it. So Collection can find this only at retrieval time and that too because of casting. So generics will ensure solving this issue.
– Kanagavelu Sugumar
Jun 8 '16 at 11:18
|
show 1 more comment
1
Isn't this because generics were added later?
– Sotirios Delimanolis
Sep 6 '13 at 21:18
1
i think comparing between arrays and collections is unfair, Collections use arrays in the background !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:35
2
@EL-conteDe-monteTereBentikh Not all collections, for exampleLinkedList.
– Paul Bellora
Sep 6 '13 at 21:35
@PaulBellora i know that Maps are different than Collection implementers, but i read in the SCPJ6 that Collections generally relied on arrays !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:39
Because there is no ArrayStoreException; when inserting wrong element in Collection where as array has it. So Collection can find this only at retrieval time and that too because of casting. So generics will ensure solving this issue.
– Kanagavelu Sugumar
Jun 8 '16 at 11:18
1
1
Isn't this because generics were added later?
– Sotirios Delimanolis
Sep 6 '13 at 21:18
Isn't this because generics were added later?
– Sotirios Delimanolis
Sep 6 '13 at 21:18
1
1
i think comparing between arrays and collections is unfair, Collections use arrays in the background !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:35
i think comparing between arrays and collections is unfair, Collections use arrays in the background !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:35
2
2
@EL-conteDe-monteTereBentikh Not all collections, for example
LinkedList.– Paul Bellora
Sep 6 '13 at 21:35
@EL-conteDe-monteTereBentikh Not all collections, for example
LinkedList.– Paul Bellora
Sep 6 '13 at 21:35
@PaulBellora i know that Maps are different than Collection implementers, but i read in the SCPJ6 that Collections generally relied on arrays !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:39
@PaulBellora i know that Maps are different than Collection implementers, but i read in the SCPJ6 that Collections generally relied on arrays !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:39
Because there is no ArrayStoreException; when inserting wrong element in Collection where as array has it. So Collection can find this only at retrieval time and that too because of casting. So generics will ensure solving this issue.
– Kanagavelu Sugumar
Jun 8 '16 at 11:18
Because there is no ArrayStoreException; when inserting wrong element in Collection where as array has it. So Collection can find this only at retrieval time and that too because of casting. So generics will ensure solving this issue.
– Kanagavelu Sugumar
Jun 8 '16 at 11:18
|
show 1 more comment
8 Answers
8
active
oldest
votes
Via wikipedia:
Early versions of Java and C# did not include generics (a.k.a. parametric polymorphism).
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 theObject.equalsmethod 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 typeboolean 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.
Therefore, both Java and C# treat array types covariantly. For instance, in C#
string[]is a subtype ofobject[], and in JavaString[]is a subtype ofObject[].
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:
No, a
List<Dog>is not aList<Animal>. Consider what you can do with aList<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?
Suddenly you have a very confused cat.
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);
2
yes, Arrays allows for polymorphic behavior, however, it does introduce runtime excpetions (unlike compile-time exceptions with generics). eg :Object[] num = new Number[4]; num[1]= 5; num[2] = 5.0f; num[3]=43.4; System.out.println(Arrays.toString(num)); num[0]="hello";
– eagertoLearn
Sep 6 '13 at 22:07
18
That's correct. Arrays have reifiable types and throwArrayStoreExceptions as needed. Clearly this was considered a worthy compromise at the time. Contrast that with today: many regard array covariance as a mistake, in retrospect.
– Paul Bellora
Sep 6 '13 at 22:18
1
Why do "many" regard it a mistake? It's far more useful than not having array covariance. How often have you seen an ArrayStoreException; they are quite rare. The irony here is unforgivable imo... among the very worst mistakes ever made in Java is use-site variance aka wildcards.
– Scott
Sep 6 '15 at 21:09
3
@ScottMcKinney: "Why do "many" regard it a mistake?" AIUI, this is because array covariance requires dynamic type tests on all array assignment operations (although compiler optimizations can perhaps help?) which can cause a significant runtime overhead.
– Dominique Devriese
Oct 26 '15 at 14:58
Thanks, Dominique, but from my observation it appears the reason "many" regard it a mistake is more along the lines of parroting what a few others have said. Again, taking a fresh look at array covariance, it's far more useful than damaging. Again, the actual BIG mistake Java made was use-site generic variance via wildcards. That has caused more problems than I think "many" want to admit.
– Scott
Feb 4 '16 at 20:41
|
show 1 more comment
The reason is that every array knows its element type during runtime, while generic collection doesn't because of type erasure.
For example:
String[] strings = new String[2];
Object[] objects = strings; // valid, String[] is Object[]
objects[0] = 12; // error, would cause java.lang.ArrayStoreException: java.lang.Integer during runtime
If this was allowed with generic collections:
List<String> strings = new ArrayList<String>();
List<Object> objects = strings; // let's say it is valid
objects.add(12); // invalid, Integer should not be put into List<String> but there is no information during runtime to catch this
But this would cause problems later when someone would try to access the list:
String first = strings.get(0); // would cause ClassCastException, trying to assign 12 to String
I think Paul Bellora answer is more appropriate as he comments on WHY Arrays are covariant. If arrays were made invariant, then its fine. you would have type erasure with it. The main reason for type Erasure property is for backward compatibility correct?
– eagertoLearn
Sep 6 '13 at 21:57
@user2708477, yes, type erasure was introduced because of backward compatibility. And yes, my answer tries to answer the question in the title, why generics are invariant.
– Katona
Sep 6 '13 at 22:01
The fact that arrays know their type means that while covariance allows code to ask to store something into an array where it won't fit--it doesn't mean such a store will be allowed to take place. Consequently, the level of danger introduced by having arrays be covariant is much less than it would be if they didn't know their types.
– supercat
Sep 6 '13 at 22:14
@supercat, correct, what I wanted to point out is that for generics with type erasure in place, covariance could not have been implemented with the minimal safety of runtime checks
– Katona
Sep 7 '13 at 3:08
1
I personally think this answer provides the right explanation as to why Arrays are covariant when Collections couldn't be. Thanks!
– asgs
Feb 19 '17 at 20:47
|
show 2 more comments
May be this help:-
Generics are not covariant
Arrays in the Java language are covariant -- which means that if Integer extends Number (which it does), then not only is an Integer also a Number, but an Integer[] is also a Number[], and you are free to pass or assign an Integer[] where a Number[] is called for. (More formally, if Number is a supertype of Integer, then Number[] is a supertype of Integer[].) You might think the same is true of generic types as well -- that List<Number> is a supertype of List<Integer>, and that you can pass a List<Integer> where a List<Number> is expected. Unfortunately, it doesn't work that way.
It turns out there's a good reason it doesn't work that way: It would break the type safety generics were supposed to provide. Imagine you could assign a List<Integer> to a List<Number>.
Then the following code would allow you to put something that wasn't an Integer into a List<Integer>:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));
Because ln is a List<Number>, adding a Float to it seems perfectly legal. But if ln were aliased with li, then it would break the type-safety promise implicit in the definition of li -- that it is a list of integers, which is why generic types cannot be covariant.
3
For Arrays, you get anArrayStoreExceptionat runtime.
– Sotirios Delimanolis
Sep 6 '13 at 21:25
4
my question isWHYis Arrays made covariant. as Sotirios mentioned, with Arrays one would get ArrayStoreException at runtime, if Arrays were made invariant, then we could detect this error at compile time itself correct?
– eagertoLearn
Sep 6 '13 at 21:52
@eagertoLearn: One major semantic weakness of Java is that it nothing in its type system can distinguish "Array which holds nothing but derivatives ofAnimal, which doesn't have to accept any items received from elsewhere" from "Array which must contain nothing butAnimal, and must be willing to accept externally-supplied references toAnimal. Code which needs the former should accept an array ofCat, but code which needs the latter shouldn't. If the compiler could distinguish the two types, it could provide compile-time checking. Unfortunately, the only thing distinguishing them...
– supercat
Jun 16 '14 at 22:14
...is whether code actually tries to store anything into them, and there's no way to know that until runtime.
– supercat
Jun 16 '14 at 22:14
add a comment |
Arrays are covariant for at least two reasons:
It is useful for collections that hold information which will never change to be covariant. For a collection of T to be covariant, its backing store must also be covariant. While one could design an immutable
Tcollection which did not use aT[]as its backing store (e.g. using a tree or linked list), such a collection would be unlikely to perform as well as one backed by an array. One might argue that a better way to provide for covariant immutable collections would have been to define a "covariant immutable array" type they could use a backing store, but simply allowing array covariance was probably easier.Arrays will frequently be mutated by code which doesn't know what type of thing is going to be in them, but won't put into the array anything which wasn't read out of that same array. A prime example of this is sorting code. Conceptually it might have been possible for array types to include methods to swap or permute elements (such methods could be equally applicable to any array type), or define an "array manipulator" object which hold a reference to an array and one or more things that had been read from it, and could include methods to store previously-read items into the array from which they had come. If arrays were not covariant, user code would not be able to define such a type, but the runtime could have included some specialized methods.
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.-- good point
– eagertoLearn
Sep 6 '13 at 22:19
add a comment |
An important feature of parametric types is the ability to write polymorphic algorithms, i.e. algorithms that operate on a data structure regardless of its parameter value, such as Arrays.sort().
With generics, that's done with wildcard types:
<E extends Comparable<E>> void sort(E[]);
To be truly useful, wildcard types require wildcard capture, and that requires the notion of a type parameter. None of that was available at the time arrays were added to Java, and makings arrays of reference type covariant permitted a far simpler way to permit polymorphic algorithms:
void sort(Comparable[]);
However, that simplicity opened a loophole in the static type system:
String[] strings = "hello";
Object[] objects = strings;
objects[0] = 1; // throws ArrayStoreException
requiring a runtime check of every write access to an array of reference type.
In a nutshell, the newer approach embodied by generics makes the type system more complex, but also more statically type safe, while the older approach was simpler, and less statically type safe. The designers of the language opted for the simpler approach, having more important things to do than closing a small loophole in the type system that rarely causes problems. Later, when Java was established, and the pressing needs taken care of, they had the resources to do it right for generics (but changing it for arrays would have broken existing Java programs).
add a comment |
Generics are invariant: from JSL 4.10:
...Subtyping does not extend through generic types: T <: U does not
imply thatC<T><:C<U>...
and a few lines further, JLS also explains that
Arrays are covariant (first bullet):
4.10.3 Subtyping among Array Types

add a comment |
My take: When code is expecting an array A[] and you give it B[] where B is a subclass of A, there's only two things to worry about: what happens when you read an array element, and what happens if you write it. So it's not hard to write language rules to ensure that type safety is preserved in all cases (the main rule being that an ArrayStoreException could be thrown if you try to stick an A into a B[]). For a generic, though, when you declare a class SomeClass<T>, there can be any number of ways T is used in the body of the class, and I'm guessing it's just way too complicated to work out all the possible combinations to write rules about when things are allowed and when they aren't.
add a comment |
I think they made a wrong decision at the first place that made array covariant. It breaks the type safety as it described here and they got stuck with that because of backward compatibility and after that they tried to not make the same mistake for generic.
And that's one of the reasons that Joshua Bloch prefers lists to arra ys in Item 25 of book "Effective Java(second edition)"
Josh Block was the author of Java's collections framework (1.2), and the author of Java's generics (1.5). So the guy who built the generics that everyone complains about is also coincidentally the guy who wrote the book saying that they are the better way to go? Not a huge surprise!
– cpurdy
Dec 9 '16 at 20:17
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f18666710%2fwhy-are-arrays-covariant-but-generics-are-invariant%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
8 Answers
8
active
oldest
votes
8 Answers
8
active
oldest
votes
active
oldest
votes
active
oldest
votes
Via wikipedia:
Early versions of Java and C# did not include generics (a.k.a. parametric polymorphism).
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 theObject.equalsmethod 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 typeboolean 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.
Therefore, both Java and C# treat array types covariantly. For instance, in C#
string[]is a subtype ofobject[], and in JavaString[]is a subtype ofObject[].
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:
No, a
List<Dog>is not aList<Animal>. Consider what you can do with aList<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?
Suddenly you have a very confused cat.
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);
2
yes, Arrays allows for polymorphic behavior, however, it does introduce runtime excpetions (unlike compile-time exceptions with generics). eg :Object[] num = new Number[4]; num[1]= 5; num[2] = 5.0f; num[3]=43.4; System.out.println(Arrays.toString(num)); num[0]="hello";
– eagertoLearn
Sep 6 '13 at 22:07
18
That's correct. Arrays have reifiable types and throwArrayStoreExceptions as needed. Clearly this was considered a worthy compromise at the time. Contrast that with today: many regard array covariance as a mistake, in retrospect.
– Paul Bellora
Sep 6 '13 at 22:18
1
Why do "many" regard it a mistake? It's far more useful than not having array covariance. How often have you seen an ArrayStoreException; they are quite rare. The irony here is unforgivable imo... among the very worst mistakes ever made in Java is use-site variance aka wildcards.
– Scott
Sep 6 '15 at 21:09
3
@ScottMcKinney: "Why do "many" regard it a mistake?" AIUI, this is because array covariance requires dynamic type tests on all array assignment operations (although compiler optimizations can perhaps help?) which can cause a significant runtime overhead.
– Dominique Devriese
Oct 26 '15 at 14:58
Thanks, Dominique, but from my observation it appears the reason "many" regard it a mistake is more along the lines of parroting what a few others have said. Again, taking a fresh look at array covariance, it's far more useful than damaging. Again, the actual BIG mistake Java made was use-site generic variance via wildcards. That has caused more problems than I think "many" want to admit.
– Scott
Feb 4 '16 at 20:41
|
show 1 more comment
Via wikipedia:
Early versions of Java and C# did not include generics (a.k.a. parametric polymorphism).
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 theObject.equalsmethod 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 typeboolean 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.
Therefore, both Java and C# treat array types covariantly. For instance, in C#
string[]is a subtype ofobject[], and in JavaString[]is a subtype ofObject[].
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:
No, a
List<Dog>is not aList<Animal>. Consider what you can do with aList<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?
Suddenly you have a very confused cat.
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);
2
yes, Arrays allows for polymorphic behavior, however, it does introduce runtime excpetions (unlike compile-time exceptions with generics). eg :Object[] num = new Number[4]; num[1]= 5; num[2] = 5.0f; num[3]=43.4; System.out.println(Arrays.toString(num)); num[0]="hello";
– eagertoLearn
Sep 6 '13 at 22:07
18
That's correct. Arrays have reifiable types and throwArrayStoreExceptions as needed. Clearly this was considered a worthy compromise at the time. Contrast that with today: many regard array covariance as a mistake, in retrospect.
– Paul Bellora
Sep 6 '13 at 22:18
1
Why do "many" regard it a mistake? It's far more useful than not having array covariance. How often have you seen an ArrayStoreException; they are quite rare. The irony here is unforgivable imo... among the very worst mistakes ever made in Java is use-site variance aka wildcards.
– Scott
Sep 6 '15 at 21:09
3
@ScottMcKinney: "Why do "many" regard it a mistake?" AIUI, this is because array covariance requires dynamic type tests on all array assignment operations (although compiler optimizations can perhaps help?) which can cause a significant runtime overhead.
– Dominique Devriese
Oct 26 '15 at 14:58
Thanks, Dominique, but from my observation it appears the reason "many" regard it a mistake is more along the lines of parroting what a few others have said. Again, taking a fresh look at array covariance, it's far more useful than damaging. Again, the actual BIG mistake Java made was use-site generic variance via wildcards. That has caused more problems than I think "many" want to admit.
– Scott
Feb 4 '16 at 20:41
|
show 1 more comment
Via wikipedia:
Early versions of Java and C# did not include generics (a.k.a. parametric polymorphism).
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 theObject.equalsmethod 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 typeboolean 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.
Therefore, both Java and C# treat array types covariantly. For instance, in C#
string[]is a subtype ofobject[], and in JavaString[]is a subtype ofObject[].
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:
No, a
List<Dog>is not aList<Animal>. Consider what you can do with aList<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?
Suddenly you have a very confused cat.
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);
Via wikipedia:
Early versions of Java and C# did not include generics (a.k.a. parametric polymorphism).
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 theObject.equalsmethod 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 typeboolean 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.
Therefore, both Java and C# treat array types covariantly. For instance, in C#
string[]is a subtype ofobject[], and in JavaString[]is a subtype ofObject[].
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:
No, a
List<Dog>is not aList<Animal>. Consider what you can do with aList<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?
Suddenly you have a very confused cat.
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);
edited May 23 '17 at 12:34
Community♦
11
11
answered Sep 6 '13 at 21:30
Paul BelloraPaul Bellora
46.3k16114164
46.3k16114164
2
yes, Arrays allows for polymorphic behavior, however, it does introduce runtime excpetions (unlike compile-time exceptions with generics). eg :Object[] num = new Number[4]; num[1]= 5; num[2] = 5.0f; num[3]=43.4; System.out.println(Arrays.toString(num)); num[0]="hello";
– eagertoLearn
Sep 6 '13 at 22:07
18
That's correct. Arrays have reifiable types and throwArrayStoreExceptions as needed. Clearly this was considered a worthy compromise at the time. Contrast that with today: many regard array covariance as a mistake, in retrospect.
– Paul Bellora
Sep 6 '13 at 22:18
1
Why do "many" regard it a mistake? It's far more useful than not having array covariance. How often have you seen an ArrayStoreException; they are quite rare. The irony here is unforgivable imo... among the very worst mistakes ever made in Java is use-site variance aka wildcards.
– Scott
Sep 6 '15 at 21:09
3
@ScottMcKinney: "Why do "many" regard it a mistake?" AIUI, this is because array covariance requires dynamic type tests on all array assignment operations (although compiler optimizations can perhaps help?) which can cause a significant runtime overhead.
– Dominique Devriese
Oct 26 '15 at 14:58
Thanks, Dominique, but from my observation it appears the reason "many" regard it a mistake is more along the lines of parroting what a few others have said. Again, taking a fresh look at array covariance, it's far more useful than damaging. Again, the actual BIG mistake Java made was use-site generic variance via wildcards. That has caused more problems than I think "many" want to admit.
– Scott
Feb 4 '16 at 20:41
|
show 1 more comment
2
yes, Arrays allows for polymorphic behavior, however, it does introduce runtime excpetions (unlike compile-time exceptions with generics). eg :Object[] num = new Number[4]; num[1]= 5; num[2] = 5.0f; num[3]=43.4; System.out.println(Arrays.toString(num)); num[0]="hello";
– eagertoLearn
Sep 6 '13 at 22:07
18
That's correct. Arrays have reifiable types and throwArrayStoreExceptions as needed. Clearly this was considered a worthy compromise at the time. Contrast that with today: many regard array covariance as a mistake, in retrospect.
– Paul Bellora
Sep 6 '13 at 22:18
1
Why do "many" regard it a mistake? It's far more useful than not having array covariance. How often have you seen an ArrayStoreException; they are quite rare. The irony here is unforgivable imo... among the very worst mistakes ever made in Java is use-site variance aka wildcards.
– Scott
Sep 6 '15 at 21:09
3
@ScottMcKinney: "Why do "many" regard it a mistake?" AIUI, this is because array covariance requires dynamic type tests on all array assignment operations (although compiler optimizations can perhaps help?) which can cause a significant runtime overhead.
– Dominique Devriese
Oct 26 '15 at 14:58
Thanks, Dominique, but from my observation it appears the reason "many" regard it a mistake is more along the lines of parroting what a few others have said. Again, taking a fresh look at array covariance, it's far more useful than damaging. Again, the actual BIG mistake Java made was use-site generic variance via wildcards. That has caused more problems than I think "many" want to admit.
– Scott
Feb 4 '16 at 20:41
2
2
yes, Arrays allows for polymorphic behavior, however, it does introduce runtime excpetions (unlike compile-time exceptions with generics). eg :
Object[] num = new Number[4]; num[1]= 5; num[2] = 5.0f; num[3]=43.4; System.out.println(Arrays.toString(num)); num[0]="hello";– eagertoLearn
Sep 6 '13 at 22:07
yes, Arrays allows for polymorphic behavior, however, it does introduce runtime excpetions (unlike compile-time exceptions with generics). eg :
Object[] num = new Number[4]; num[1]= 5; num[2] = 5.0f; num[3]=43.4; System.out.println(Arrays.toString(num)); num[0]="hello";– eagertoLearn
Sep 6 '13 at 22:07
18
18
That's correct. Arrays have reifiable types and throw
ArrayStoreExceptions as needed. Clearly this was considered a worthy compromise at the time. Contrast that with today: many regard array covariance as a mistake, in retrospect.– Paul Bellora
Sep 6 '13 at 22:18
That's correct. Arrays have reifiable types and throw
ArrayStoreExceptions as needed. Clearly this was considered a worthy compromise at the time. Contrast that with today: many regard array covariance as a mistake, in retrospect.– Paul Bellora
Sep 6 '13 at 22:18
1
1
Why do "many" regard it a mistake? It's far more useful than not having array covariance. How often have you seen an ArrayStoreException; they are quite rare. The irony here is unforgivable imo... among the very worst mistakes ever made in Java is use-site variance aka wildcards.
– Scott
Sep 6 '15 at 21:09
Why do "many" regard it a mistake? It's far more useful than not having array covariance. How often have you seen an ArrayStoreException; they are quite rare. The irony here is unforgivable imo... among the very worst mistakes ever made in Java is use-site variance aka wildcards.
– Scott
Sep 6 '15 at 21:09
3
3
@ScottMcKinney: "Why do "many" regard it a mistake?" AIUI, this is because array covariance requires dynamic type tests on all array assignment operations (although compiler optimizations can perhaps help?) which can cause a significant runtime overhead.
– Dominique Devriese
Oct 26 '15 at 14:58
@ScottMcKinney: "Why do "many" regard it a mistake?" AIUI, this is because array covariance requires dynamic type tests on all array assignment operations (although compiler optimizations can perhaps help?) which can cause a significant runtime overhead.
– Dominique Devriese
Oct 26 '15 at 14:58
Thanks, Dominique, but from my observation it appears the reason "many" regard it a mistake is more along the lines of parroting what a few others have said. Again, taking a fresh look at array covariance, it's far more useful than damaging. Again, the actual BIG mistake Java made was use-site generic variance via wildcards. That has caused more problems than I think "many" want to admit.
– Scott
Feb 4 '16 at 20:41
Thanks, Dominique, but from my observation it appears the reason "many" regard it a mistake is more along the lines of parroting what a few others have said. Again, taking a fresh look at array covariance, it's far more useful than damaging. Again, the actual BIG mistake Java made was use-site generic variance via wildcards. That has caused more problems than I think "many" want to admit.
– Scott
Feb 4 '16 at 20:41
|
show 1 more comment
The reason is that every array knows its element type during runtime, while generic collection doesn't because of type erasure.
For example:
String[] strings = new String[2];
Object[] objects = strings; // valid, String[] is Object[]
objects[0] = 12; // error, would cause java.lang.ArrayStoreException: java.lang.Integer during runtime
If this was allowed with generic collections:
List<String> strings = new ArrayList<String>();
List<Object> objects = strings; // let's say it is valid
objects.add(12); // invalid, Integer should not be put into List<String> but there is no information during runtime to catch this
But this would cause problems later when someone would try to access the list:
String first = strings.get(0); // would cause ClassCastException, trying to assign 12 to String
I think Paul Bellora answer is more appropriate as he comments on WHY Arrays are covariant. If arrays were made invariant, then its fine. you would have type erasure with it. The main reason for type Erasure property is for backward compatibility correct?
– eagertoLearn
Sep 6 '13 at 21:57
@user2708477, yes, type erasure was introduced because of backward compatibility. And yes, my answer tries to answer the question in the title, why generics are invariant.
– Katona
Sep 6 '13 at 22:01
The fact that arrays know their type means that while covariance allows code to ask to store something into an array where it won't fit--it doesn't mean such a store will be allowed to take place. Consequently, the level of danger introduced by having arrays be covariant is much less than it would be if they didn't know their types.
– supercat
Sep 6 '13 at 22:14
@supercat, correct, what I wanted to point out is that for generics with type erasure in place, covariance could not have been implemented with the minimal safety of runtime checks
– Katona
Sep 7 '13 at 3:08
1
I personally think this answer provides the right explanation as to why Arrays are covariant when Collections couldn't be. Thanks!
– asgs
Feb 19 '17 at 20:47
|
show 2 more comments
The reason is that every array knows its element type during runtime, while generic collection doesn't because of type erasure.
For example:
String[] strings = new String[2];
Object[] objects = strings; // valid, String[] is Object[]
objects[0] = 12; // error, would cause java.lang.ArrayStoreException: java.lang.Integer during runtime
If this was allowed with generic collections:
List<String> strings = new ArrayList<String>();
List<Object> objects = strings; // let's say it is valid
objects.add(12); // invalid, Integer should not be put into List<String> but there is no information during runtime to catch this
But this would cause problems later when someone would try to access the list:
String first = strings.get(0); // would cause ClassCastException, trying to assign 12 to String
I think Paul Bellora answer is more appropriate as he comments on WHY Arrays are covariant. If arrays were made invariant, then its fine. you would have type erasure with it. The main reason for type Erasure property is for backward compatibility correct?
– eagertoLearn
Sep 6 '13 at 21:57
@user2708477, yes, type erasure was introduced because of backward compatibility. And yes, my answer tries to answer the question in the title, why generics are invariant.
– Katona
Sep 6 '13 at 22:01
The fact that arrays know their type means that while covariance allows code to ask to store something into an array where it won't fit--it doesn't mean such a store will be allowed to take place. Consequently, the level of danger introduced by having arrays be covariant is much less than it would be if they didn't know their types.
– supercat
Sep 6 '13 at 22:14
@supercat, correct, what I wanted to point out is that for generics with type erasure in place, covariance could not have been implemented with the minimal safety of runtime checks
– Katona
Sep 7 '13 at 3:08
1
I personally think this answer provides the right explanation as to why Arrays are covariant when Collections couldn't be. Thanks!
– asgs
Feb 19 '17 at 20:47
|
show 2 more comments
The reason is that every array knows its element type during runtime, while generic collection doesn't because of type erasure.
For example:
String[] strings = new String[2];
Object[] objects = strings; // valid, String[] is Object[]
objects[0] = 12; // error, would cause java.lang.ArrayStoreException: java.lang.Integer during runtime
If this was allowed with generic collections:
List<String> strings = new ArrayList<String>();
List<Object> objects = strings; // let's say it is valid
objects.add(12); // invalid, Integer should not be put into List<String> but there is no information during runtime to catch this
But this would cause problems later when someone would try to access the list:
String first = strings.get(0); // would cause ClassCastException, trying to assign 12 to String
The reason is that every array knows its element type during runtime, while generic collection doesn't because of type erasure.
For example:
String[] strings = new String[2];
Object[] objects = strings; // valid, String[] is Object[]
objects[0] = 12; // error, would cause java.lang.ArrayStoreException: java.lang.Integer during runtime
If this was allowed with generic collections:
List<String> strings = new ArrayList<String>();
List<Object> objects = strings; // let's say it is valid
objects.add(12); // invalid, Integer should not be put into List<String> but there is no information during runtime to catch this
But this would cause problems later when someone would try to access the list:
String first = strings.get(0); // would cause ClassCastException, trying to assign 12 to String
edited Nov 2 '18 at 20:50
MC Emperor
9,654125690
9,654125690
answered Sep 6 '13 at 21:34
KatonaKatona
3,7391723
3,7391723
I think Paul Bellora answer is more appropriate as he comments on WHY Arrays are covariant. If arrays were made invariant, then its fine. you would have type erasure with it. The main reason for type Erasure property is for backward compatibility correct?
– eagertoLearn
Sep 6 '13 at 21:57
@user2708477, yes, type erasure was introduced because of backward compatibility. And yes, my answer tries to answer the question in the title, why generics are invariant.
– Katona
Sep 6 '13 at 22:01
The fact that arrays know their type means that while covariance allows code to ask to store something into an array where it won't fit--it doesn't mean such a store will be allowed to take place. Consequently, the level of danger introduced by having arrays be covariant is much less than it would be if they didn't know their types.
– supercat
Sep 6 '13 at 22:14
@supercat, correct, what I wanted to point out is that for generics with type erasure in place, covariance could not have been implemented with the minimal safety of runtime checks
– Katona
Sep 7 '13 at 3:08
1
I personally think this answer provides the right explanation as to why Arrays are covariant when Collections couldn't be. Thanks!
– asgs
Feb 19 '17 at 20:47
|
show 2 more comments
I think Paul Bellora answer is more appropriate as he comments on WHY Arrays are covariant. If arrays were made invariant, then its fine. you would have type erasure with it. The main reason for type Erasure property is for backward compatibility correct?
– eagertoLearn
Sep 6 '13 at 21:57
@user2708477, yes, type erasure was introduced because of backward compatibility. And yes, my answer tries to answer the question in the title, why generics are invariant.
– Katona
Sep 6 '13 at 22:01
The fact that arrays know their type means that while covariance allows code to ask to store something into an array where it won't fit--it doesn't mean such a store will be allowed to take place. Consequently, the level of danger introduced by having arrays be covariant is much less than it would be if they didn't know their types.
– supercat
Sep 6 '13 at 22:14
@supercat, correct, what I wanted to point out is that for generics with type erasure in place, covariance could not have been implemented with the minimal safety of runtime checks
– Katona
Sep 7 '13 at 3:08
1
I personally think this answer provides the right explanation as to why Arrays are covariant when Collections couldn't be. Thanks!
– asgs
Feb 19 '17 at 20:47
I think Paul Bellora answer is more appropriate as he comments on WHY Arrays are covariant. If arrays were made invariant, then its fine. you would have type erasure with it. The main reason for type Erasure property is for backward compatibility correct?
– eagertoLearn
Sep 6 '13 at 21:57
I think Paul Bellora answer is more appropriate as he comments on WHY Arrays are covariant. If arrays were made invariant, then its fine. you would have type erasure with it. The main reason for type Erasure property is for backward compatibility correct?
– eagertoLearn
Sep 6 '13 at 21:57
@user2708477, yes, type erasure was introduced because of backward compatibility. And yes, my answer tries to answer the question in the title, why generics are invariant.
– Katona
Sep 6 '13 at 22:01
@user2708477, yes, type erasure was introduced because of backward compatibility. And yes, my answer tries to answer the question in the title, why generics are invariant.
– Katona
Sep 6 '13 at 22:01
The fact that arrays know their type means that while covariance allows code to ask to store something into an array where it won't fit--it doesn't mean such a store will be allowed to take place. Consequently, the level of danger introduced by having arrays be covariant is much less than it would be if they didn't know their types.
– supercat
Sep 6 '13 at 22:14
The fact that arrays know their type means that while covariance allows code to ask to store something into an array where it won't fit--it doesn't mean such a store will be allowed to take place. Consequently, the level of danger introduced by having arrays be covariant is much less than it would be if they didn't know their types.
– supercat
Sep 6 '13 at 22:14
@supercat, correct, what I wanted to point out is that for generics with type erasure in place, covariance could not have been implemented with the minimal safety of runtime checks
– Katona
Sep 7 '13 at 3:08
@supercat, correct, what I wanted to point out is that for generics with type erasure in place, covariance could not have been implemented with the minimal safety of runtime checks
– Katona
Sep 7 '13 at 3:08
1
1
I personally think this answer provides the right explanation as to why Arrays are covariant when Collections couldn't be. Thanks!
– asgs
Feb 19 '17 at 20:47
I personally think this answer provides the right explanation as to why Arrays are covariant when Collections couldn't be. Thanks!
– asgs
Feb 19 '17 at 20:47
|
show 2 more comments
May be this help:-
Generics are not covariant
Arrays in the Java language are covariant -- which means that if Integer extends Number (which it does), then not only is an Integer also a Number, but an Integer[] is also a Number[], and you are free to pass or assign an Integer[] where a Number[] is called for. (More formally, if Number is a supertype of Integer, then Number[] is a supertype of Integer[].) You might think the same is true of generic types as well -- that List<Number> is a supertype of List<Integer>, and that you can pass a List<Integer> where a List<Number> is expected. Unfortunately, it doesn't work that way.
It turns out there's a good reason it doesn't work that way: It would break the type safety generics were supposed to provide. Imagine you could assign a List<Integer> to a List<Number>.
Then the following code would allow you to put something that wasn't an Integer into a List<Integer>:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));
Because ln is a List<Number>, adding a Float to it seems perfectly legal. But if ln were aliased with li, then it would break the type-safety promise implicit in the definition of li -- that it is a list of integers, which is why generic types cannot be covariant.
3
For Arrays, you get anArrayStoreExceptionat runtime.
– Sotirios Delimanolis
Sep 6 '13 at 21:25
4
my question isWHYis Arrays made covariant. as Sotirios mentioned, with Arrays one would get ArrayStoreException at runtime, if Arrays were made invariant, then we could detect this error at compile time itself correct?
– eagertoLearn
Sep 6 '13 at 21:52
@eagertoLearn: One major semantic weakness of Java is that it nothing in its type system can distinguish "Array which holds nothing but derivatives ofAnimal, which doesn't have to accept any items received from elsewhere" from "Array which must contain nothing butAnimal, and must be willing to accept externally-supplied references toAnimal. Code which needs the former should accept an array ofCat, but code which needs the latter shouldn't. If the compiler could distinguish the two types, it could provide compile-time checking. Unfortunately, the only thing distinguishing them...
– supercat
Jun 16 '14 at 22:14
...is whether code actually tries to store anything into them, and there's no way to know that until runtime.
– supercat
Jun 16 '14 at 22:14
add a comment |
May be this help:-
Generics are not covariant
Arrays in the Java language are covariant -- which means that if Integer extends Number (which it does), then not only is an Integer also a Number, but an Integer[] is also a Number[], and you are free to pass or assign an Integer[] where a Number[] is called for. (More formally, if Number is a supertype of Integer, then Number[] is a supertype of Integer[].) You might think the same is true of generic types as well -- that List<Number> is a supertype of List<Integer>, and that you can pass a List<Integer> where a List<Number> is expected. Unfortunately, it doesn't work that way.
It turns out there's a good reason it doesn't work that way: It would break the type safety generics were supposed to provide. Imagine you could assign a List<Integer> to a List<Number>.
Then the following code would allow you to put something that wasn't an Integer into a List<Integer>:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));
Because ln is a List<Number>, adding a Float to it seems perfectly legal. But if ln were aliased with li, then it would break the type-safety promise implicit in the definition of li -- that it is a list of integers, which is why generic types cannot be covariant.
3
For Arrays, you get anArrayStoreExceptionat runtime.
– Sotirios Delimanolis
Sep 6 '13 at 21:25
4
my question isWHYis Arrays made covariant. as Sotirios mentioned, with Arrays one would get ArrayStoreException at runtime, if Arrays were made invariant, then we could detect this error at compile time itself correct?
– eagertoLearn
Sep 6 '13 at 21:52
@eagertoLearn: One major semantic weakness of Java is that it nothing in its type system can distinguish "Array which holds nothing but derivatives ofAnimal, which doesn't have to accept any items received from elsewhere" from "Array which must contain nothing butAnimal, and must be willing to accept externally-supplied references toAnimal. Code which needs the former should accept an array ofCat, but code which needs the latter shouldn't. If the compiler could distinguish the two types, it could provide compile-time checking. Unfortunately, the only thing distinguishing them...
– supercat
Jun 16 '14 at 22:14
...is whether code actually tries to store anything into them, and there's no way to know that until runtime.
– supercat
Jun 16 '14 at 22:14
add a comment |
May be this help:-
Generics are not covariant
Arrays in the Java language are covariant -- which means that if Integer extends Number (which it does), then not only is an Integer also a Number, but an Integer[] is also a Number[], and you are free to pass or assign an Integer[] where a Number[] is called for. (More formally, if Number is a supertype of Integer, then Number[] is a supertype of Integer[].) You might think the same is true of generic types as well -- that List<Number> is a supertype of List<Integer>, and that you can pass a List<Integer> where a List<Number> is expected. Unfortunately, it doesn't work that way.
It turns out there's a good reason it doesn't work that way: It would break the type safety generics were supposed to provide. Imagine you could assign a List<Integer> to a List<Number>.
Then the following code would allow you to put something that wasn't an Integer into a List<Integer>:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));
Because ln is a List<Number>, adding a Float to it seems perfectly legal. But if ln were aliased with li, then it would break the type-safety promise implicit in the definition of li -- that it is a list of integers, which is why generic types cannot be covariant.
May be this help:-
Generics are not covariant
Arrays in the Java language are covariant -- which means that if Integer extends Number (which it does), then not only is an Integer also a Number, but an Integer[] is also a Number[], and you are free to pass or assign an Integer[] where a Number[] is called for. (More formally, if Number is a supertype of Integer, then Number[] is a supertype of Integer[].) You might think the same is true of generic types as well -- that List<Number> is a supertype of List<Integer>, and that you can pass a List<Integer> where a List<Number> is expected. Unfortunately, it doesn't work that way.
It turns out there's a good reason it doesn't work that way: It would break the type safety generics were supposed to provide. Imagine you could assign a List<Integer> to a List<Number>.
Then the following code would allow you to put something that wasn't an Integer into a List<Integer>:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));
Because ln is a List<Number>, adding a Float to it seems perfectly legal. But if ln were aliased with li, then it would break the type-safety promise implicit in the definition of li -- that it is a list of integers, which is why generic types cannot be covariant.
edited Sep 6 '13 at 21:28
Jim Garrison
73.6k14126165
73.6k14126165
answered Sep 6 '13 at 21:21
Rahul TripathiRahul Tripathi
131k21178250
131k21178250
3
For Arrays, you get anArrayStoreExceptionat runtime.
– Sotirios Delimanolis
Sep 6 '13 at 21:25
4
my question isWHYis Arrays made covariant. as Sotirios mentioned, with Arrays one would get ArrayStoreException at runtime, if Arrays were made invariant, then we could detect this error at compile time itself correct?
– eagertoLearn
Sep 6 '13 at 21:52
@eagertoLearn: One major semantic weakness of Java is that it nothing in its type system can distinguish "Array which holds nothing but derivatives ofAnimal, which doesn't have to accept any items received from elsewhere" from "Array which must contain nothing butAnimal, and must be willing to accept externally-supplied references toAnimal. Code which needs the former should accept an array ofCat, but code which needs the latter shouldn't. If the compiler could distinguish the two types, it could provide compile-time checking. Unfortunately, the only thing distinguishing them...
– supercat
Jun 16 '14 at 22:14
...is whether code actually tries to store anything into them, and there's no way to know that until runtime.
– supercat
Jun 16 '14 at 22:14
add a comment |
3
For Arrays, you get anArrayStoreExceptionat runtime.
– Sotirios Delimanolis
Sep 6 '13 at 21:25
4
my question isWHYis Arrays made covariant. as Sotirios mentioned, with Arrays one would get ArrayStoreException at runtime, if Arrays were made invariant, then we could detect this error at compile time itself correct?
– eagertoLearn
Sep 6 '13 at 21:52
@eagertoLearn: One major semantic weakness of Java is that it nothing in its type system can distinguish "Array which holds nothing but derivatives ofAnimal, which doesn't have to accept any items received from elsewhere" from "Array which must contain nothing butAnimal, and must be willing to accept externally-supplied references toAnimal. Code which needs the former should accept an array ofCat, but code which needs the latter shouldn't. If the compiler could distinguish the two types, it could provide compile-time checking. Unfortunately, the only thing distinguishing them...
– supercat
Jun 16 '14 at 22:14
...is whether code actually tries to store anything into them, and there's no way to know that until runtime.
– supercat
Jun 16 '14 at 22:14
3
3
For Arrays, you get an
ArrayStoreException at runtime.– Sotirios Delimanolis
Sep 6 '13 at 21:25
For Arrays, you get an
ArrayStoreException at runtime.– Sotirios Delimanolis
Sep 6 '13 at 21:25
4
4
my question is
WHY is Arrays made covariant. as Sotirios mentioned, with Arrays one would get ArrayStoreException at runtime, if Arrays were made invariant, then we could detect this error at compile time itself correct?– eagertoLearn
Sep 6 '13 at 21:52
my question is
WHY is Arrays made covariant. as Sotirios mentioned, with Arrays one would get ArrayStoreException at runtime, if Arrays were made invariant, then we could detect this error at compile time itself correct?– eagertoLearn
Sep 6 '13 at 21:52
@eagertoLearn: One major semantic weakness of Java is that it nothing in its type system can distinguish "Array which holds nothing but derivatives of
Animal, which doesn't have to accept any items received from elsewhere" from "Array which must contain nothing but Animal, and must be willing to accept externally-supplied references to Animal. Code which needs the former should accept an array of Cat, but code which needs the latter shouldn't. If the compiler could distinguish the two types, it could provide compile-time checking. Unfortunately, the only thing distinguishing them...– supercat
Jun 16 '14 at 22:14
@eagertoLearn: One major semantic weakness of Java is that it nothing in its type system can distinguish "Array which holds nothing but derivatives of
Animal, which doesn't have to accept any items received from elsewhere" from "Array which must contain nothing but Animal, and must be willing to accept externally-supplied references to Animal. Code which needs the former should accept an array of Cat, but code which needs the latter shouldn't. If the compiler could distinguish the two types, it could provide compile-time checking. Unfortunately, the only thing distinguishing them...– supercat
Jun 16 '14 at 22:14
...is whether code actually tries to store anything into them, and there's no way to know that until runtime.
– supercat
Jun 16 '14 at 22:14
...is whether code actually tries to store anything into them, and there's no way to know that until runtime.
– supercat
Jun 16 '14 at 22:14
add a comment |
Arrays are covariant for at least two reasons:
It is useful for collections that hold information which will never change to be covariant. For a collection of T to be covariant, its backing store must also be covariant. While one could design an immutable
Tcollection which did not use aT[]as its backing store (e.g. using a tree or linked list), such a collection would be unlikely to perform as well as one backed by an array. One might argue that a better way to provide for covariant immutable collections would have been to define a "covariant immutable array" type they could use a backing store, but simply allowing array covariance was probably easier.Arrays will frequently be mutated by code which doesn't know what type of thing is going to be in them, but won't put into the array anything which wasn't read out of that same array. A prime example of this is sorting code. Conceptually it might have been possible for array types to include methods to swap or permute elements (such methods could be equally applicable to any array type), or define an "array manipulator" object which hold a reference to an array and one or more things that had been read from it, and could include methods to store previously-read items into the array from which they had come. If arrays were not covariant, user code would not be able to define such a type, but the runtime could have included some specialized methods.
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.-- good point
– eagertoLearn
Sep 6 '13 at 22:19
add a comment |
Arrays are covariant for at least two reasons:
It is useful for collections that hold information which will never change to be covariant. For a collection of T to be covariant, its backing store must also be covariant. While one could design an immutable
Tcollection which did not use aT[]as its backing store (e.g. using a tree or linked list), such a collection would be unlikely to perform as well as one backed by an array. One might argue that a better way to provide for covariant immutable collections would have been to define a "covariant immutable array" type they could use a backing store, but simply allowing array covariance was probably easier.Arrays will frequently be mutated by code which doesn't know what type of thing is going to be in them, but won't put into the array anything which wasn't read out of that same array. A prime example of this is sorting code. Conceptually it might have been possible for array types to include methods to swap or permute elements (such methods could be equally applicable to any array type), or define an "array manipulator" object which hold a reference to an array and one or more things that had been read from it, and could include methods to store previously-read items into the array from which they had come. If arrays were not covariant, user code would not be able to define such a type, but the runtime could have included some specialized methods.
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.-- good point
– eagertoLearn
Sep 6 '13 at 22:19
add a comment |
Arrays are covariant for at least two reasons:
It is useful for collections that hold information which will never change to be covariant. For a collection of T to be covariant, its backing store must also be covariant. While one could design an immutable
Tcollection which did not use aT[]as its backing store (e.g. using a tree or linked list), such a collection would be unlikely to perform as well as one backed by an array. One might argue that a better way to provide for covariant immutable collections would have been to define a "covariant immutable array" type they could use a backing store, but simply allowing array covariance was probably easier.Arrays will frequently be mutated by code which doesn't know what type of thing is going to be in them, but won't put into the array anything which wasn't read out of that same array. A prime example of this is sorting code. Conceptually it might have been possible for array types to include methods to swap or permute elements (such methods could be equally applicable to any array type), or define an "array manipulator" object which hold a reference to an array and one or more things that had been read from it, and could include methods to store previously-read items into the array from which they had come. If arrays were not covariant, user code would not be able to define such a type, but the runtime could have included some specialized methods.
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.
Arrays are covariant for at least two reasons:
It is useful for collections that hold information which will never change to be covariant. For a collection of T to be covariant, its backing store must also be covariant. While one could design an immutable
Tcollection which did not use aT[]as its backing store (e.g. using a tree or linked list), such a collection would be unlikely to perform as well as one backed by an array. One might argue that a better way to provide for covariant immutable collections would have been to define a "covariant immutable array" type they could use a backing store, but simply allowing array covariance was probably easier.Arrays will frequently be mutated by code which doesn't know what type of thing is going to be in them, but won't put into the array anything which wasn't read out of that same array. A prime example of this is sorting code. Conceptually it might have been possible for array types to include methods to swap or permute elements (such methods could be equally applicable to any array type), or define an "array manipulator" object which hold a reference to an array and one or more things that had been read from it, and could include methods to store previously-read items into the array from which they had come. If arrays were not covariant, user code would not be able to define such a type, but the runtime could have included some specialized methods.
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.
answered Sep 6 '13 at 21:36
supercatsupercat
58.6k4118158
58.6k4118158
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.-- good point
– eagertoLearn
Sep 6 '13 at 22:19
add a comment |
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code.-- good point
– eagertoLearn
Sep 6 '13 at 22:19
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code. -- good point– eagertoLearn
Sep 6 '13 at 22:19
The fact that arrays are covariant may be viewed as an ugly hack, but in most cases it facilitates the creation of working code. -- good point– eagertoLearn
Sep 6 '13 at 22:19
add a comment |
An important feature of parametric types is the ability to write polymorphic algorithms, i.e. algorithms that operate on a data structure regardless of its parameter value, such as Arrays.sort().
With generics, that's done with wildcard types:
<E extends Comparable<E>> void sort(E[]);
To be truly useful, wildcard types require wildcard capture, and that requires the notion of a type parameter. None of that was available at the time arrays were added to Java, and makings arrays of reference type covariant permitted a far simpler way to permit polymorphic algorithms:
void sort(Comparable[]);
However, that simplicity opened a loophole in the static type system:
String[] strings = "hello";
Object[] objects = strings;
objects[0] = 1; // throws ArrayStoreException
requiring a runtime check of every write access to an array of reference type.
In a nutshell, the newer approach embodied by generics makes the type system more complex, but also more statically type safe, while the older approach was simpler, and less statically type safe. The designers of the language opted for the simpler approach, having more important things to do than closing a small loophole in the type system that rarely causes problems. Later, when Java was established, and the pressing needs taken care of, they had the resources to do it right for generics (but changing it for arrays would have broken existing Java programs).
add a comment |
An important feature of parametric types is the ability to write polymorphic algorithms, i.e. algorithms that operate on a data structure regardless of its parameter value, such as Arrays.sort().
With generics, that's done with wildcard types:
<E extends Comparable<E>> void sort(E[]);
To be truly useful, wildcard types require wildcard capture, and that requires the notion of a type parameter. None of that was available at the time arrays were added to Java, and makings arrays of reference type covariant permitted a far simpler way to permit polymorphic algorithms:
void sort(Comparable[]);
However, that simplicity opened a loophole in the static type system:
String[] strings = "hello";
Object[] objects = strings;
objects[0] = 1; // throws ArrayStoreException
requiring a runtime check of every write access to an array of reference type.
In a nutshell, the newer approach embodied by generics makes the type system more complex, but also more statically type safe, while the older approach was simpler, and less statically type safe. The designers of the language opted for the simpler approach, having more important things to do than closing a small loophole in the type system that rarely causes problems. Later, when Java was established, and the pressing needs taken care of, they had the resources to do it right for generics (but changing it for arrays would have broken existing Java programs).
add a comment |
An important feature of parametric types is the ability to write polymorphic algorithms, i.e. algorithms that operate on a data structure regardless of its parameter value, such as Arrays.sort().
With generics, that's done with wildcard types:
<E extends Comparable<E>> void sort(E[]);
To be truly useful, wildcard types require wildcard capture, and that requires the notion of a type parameter. None of that was available at the time arrays were added to Java, and makings arrays of reference type covariant permitted a far simpler way to permit polymorphic algorithms:
void sort(Comparable[]);
However, that simplicity opened a loophole in the static type system:
String[] strings = "hello";
Object[] objects = strings;
objects[0] = 1; // throws ArrayStoreException
requiring a runtime check of every write access to an array of reference type.
In a nutshell, the newer approach embodied by generics makes the type system more complex, but also more statically type safe, while the older approach was simpler, and less statically type safe. The designers of the language opted for the simpler approach, having more important things to do than closing a small loophole in the type system that rarely causes problems. Later, when Java was established, and the pressing needs taken care of, they had the resources to do it right for generics (but changing it for arrays would have broken existing Java programs).
An important feature of parametric types is the ability to write polymorphic algorithms, i.e. algorithms that operate on a data structure regardless of its parameter value, such as Arrays.sort().
With generics, that's done with wildcard types:
<E extends Comparable<E>> void sort(E[]);
To be truly useful, wildcard types require wildcard capture, and that requires the notion of a type parameter. None of that was available at the time arrays were added to Java, and makings arrays of reference type covariant permitted a far simpler way to permit polymorphic algorithms:
void sort(Comparable[]);
However, that simplicity opened a loophole in the static type system:
String[] strings = "hello";
Object[] objects = strings;
objects[0] = 1; // throws ArrayStoreException
requiring a runtime check of every write access to an array of reference type.
In a nutshell, the newer approach embodied by generics makes the type system more complex, but also more statically type safe, while the older approach was simpler, and less statically type safe. The designers of the language opted for the simpler approach, having more important things to do than closing a small loophole in the type system that rarely causes problems. Later, when Java was established, and the pressing needs taken care of, they had the resources to do it right for generics (but changing it for arrays would have broken existing Java programs).
answered Sep 13 '13 at 17:48
meritonmeriton
53.8k1383146
53.8k1383146
add a comment |
add a comment |
Generics are invariant: from JSL 4.10:
...Subtyping does not extend through generic types: T <: U does not
imply thatC<T><:C<U>...
and a few lines further, JLS also explains that
Arrays are covariant (first bullet):
4.10.3 Subtyping among Array Types

add a comment |
Generics are invariant: from JSL 4.10:
...Subtyping does not extend through generic types: T <: U does not
imply thatC<T><:C<U>...
and a few lines further, JLS also explains that
Arrays are covariant (first bullet):
4.10.3 Subtyping among Array Types

add a comment |
Generics are invariant: from JSL 4.10:
...Subtyping does not extend through generic types: T <: U does not
imply thatC<T><:C<U>...
and a few lines further, JLS also explains that
Arrays are covariant (first bullet):
4.10.3 Subtyping among Array Types

Generics are invariant: from JSL 4.10:
...Subtyping does not extend through generic types: T <: U does not
imply thatC<T><:C<U>...
and a few lines further, JLS also explains that
Arrays are covariant (first bullet):
4.10.3 Subtyping among Array Types

answered Jun 15 '14 at 17:37
alfasinalfasin
43.8k105698
43.8k105698
add a comment |
add a comment |
My take: When code is expecting an array A[] and you give it B[] where B is a subclass of A, there's only two things to worry about: what happens when you read an array element, and what happens if you write it. So it's not hard to write language rules to ensure that type safety is preserved in all cases (the main rule being that an ArrayStoreException could be thrown if you try to stick an A into a B[]). For a generic, though, when you declare a class SomeClass<T>, there can be any number of ways T is used in the body of the class, and I'm guessing it's just way too complicated to work out all the possible combinations to write rules about when things are allowed and when they aren't.
add a comment |
My take: When code is expecting an array A[] and you give it B[] where B is a subclass of A, there's only two things to worry about: what happens when you read an array element, and what happens if you write it. So it's not hard to write language rules to ensure that type safety is preserved in all cases (the main rule being that an ArrayStoreException could be thrown if you try to stick an A into a B[]). For a generic, though, when you declare a class SomeClass<T>, there can be any number of ways T is used in the body of the class, and I'm guessing it's just way too complicated to work out all the possible combinations to write rules about when things are allowed and when they aren't.
add a comment |
My take: When code is expecting an array A[] and you give it B[] where B is a subclass of A, there's only two things to worry about: what happens when you read an array element, and what happens if you write it. So it's not hard to write language rules to ensure that type safety is preserved in all cases (the main rule being that an ArrayStoreException could be thrown if you try to stick an A into a B[]). For a generic, though, when you declare a class SomeClass<T>, there can be any number of ways T is used in the body of the class, and I'm guessing it's just way too complicated to work out all the possible combinations to write rules about when things are allowed and when they aren't.
My take: When code is expecting an array A[] and you give it B[] where B is a subclass of A, there's only two things to worry about: what happens when you read an array element, and what happens if you write it. So it's not hard to write language rules to ensure that type safety is preserved in all cases (the main rule being that an ArrayStoreException could be thrown if you try to stick an A into a B[]). For a generic, though, when you declare a class SomeClass<T>, there can be any number of ways T is used in the body of the class, and I'm guessing it's just way too complicated to work out all the possible combinations to write rules about when things are allowed and when they aren't.
answered Sep 6 '13 at 21:56
ajbajb
27.1k33863
27.1k33863
add a comment |
add a comment |
I think they made a wrong decision at the first place that made array covariant. It breaks the type safety as it described here and they got stuck with that because of backward compatibility and after that they tried to not make the same mistake for generic.
And that's one of the reasons that Joshua Bloch prefers lists to arra ys in Item 25 of book "Effective Java(second edition)"
Josh Block was the author of Java's collections framework (1.2), and the author of Java's generics (1.5). So the guy who built the generics that everyone complains about is also coincidentally the guy who wrote the book saying that they are the better way to go? Not a huge surprise!
– cpurdy
Dec 9 '16 at 20:17
add a comment |
I think they made a wrong decision at the first place that made array covariant. It breaks the type safety as it described here and they got stuck with that because of backward compatibility and after that they tried to not make the same mistake for generic.
And that's one of the reasons that Joshua Bloch prefers lists to arra ys in Item 25 of book "Effective Java(second edition)"
Josh Block was the author of Java's collections framework (1.2), and the author of Java's generics (1.5). So the guy who built the generics that everyone complains about is also coincidentally the guy who wrote the book saying that they are the better way to go? Not a huge surprise!
– cpurdy
Dec 9 '16 at 20:17
add a comment |
I think they made a wrong decision at the first place that made array covariant. It breaks the type safety as it described here and they got stuck with that because of backward compatibility and after that they tried to not make the same mistake for generic.
And that's one of the reasons that Joshua Bloch prefers lists to arra ys in Item 25 of book "Effective Java(second edition)"
I think they made a wrong decision at the first place that made array covariant. It breaks the type safety as it described here and they got stuck with that because of backward compatibility and after that they tried to not make the same mistake for generic.
And that's one of the reasons that Joshua Bloch prefers lists to arra ys in Item 25 of book "Effective Java(second edition)"
edited May 30 '17 at 7:53
P.J.Meisch
5,65142745
5,65142745
answered Apr 1 '16 at 19:22
RezaReza
864716
864716
Josh Block was the author of Java's collections framework (1.2), and the author of Java's generics (1.5). So the guy who built the generics that everyone complains about is also coincidentally the guy who wrote the book saying that they are the better way to go? Not a huge surprise!
– cpurdy
Dec 9 '16 at 20:17
add a comment |
Josh Block was the author of Java's collections framework (1.2), and the author of Java's generics (1.5). So the guy who built the generics that everyone complains about is also coincidentally the guy who wrote the book saying that they are the better way to go? Not a huge surprise!
– cpurdy
Dec 9 '16 at 20:17
Josh Block was the author of Java's collections framework (1.2), and the author of Java's generics (1.5). So the guy who built the generics that everyone complains about is also coincidentally the guy who wrote the book saying that they are the better way to go? Not a huge surprise!
– cpurdy
Dec 9 '16 at 20:17
Josh Block was the author of Java's collections framework (1.2), and the author of Java's generics (1.5). So the guy who built the generics that everyone complains about is also coincidentally the guy who wrote the book saying that they are the better way to go? Not a huge surprise!
– cpurdy
Dec 9 '16 at 20:17
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f18666710%2fwhy-are-arrays-covariant-but-generics-are-invariant%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Isn't this because generics were added later?
– Sotirios Delimanolis
Sep 6 '13 at 21:18
1
i think comparing between arrays and collections is unfair, Collections use arrays in the background !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:35
2
@EL-conteDe-monteTereBentikh Not all collections, for example
LinkedList.– Paul Bellora
Sep 6 '13 at 21:35
@PaulBellora i know that Maps are different than Collection implementers, but i read in the SCPJ6 that Collections generally relied on arrays !!
– Ahmed Adel Ismail
Sep 6 '13 at 21:39
Because there is no ArrayStoreException; when inserting wrong element in Collection where as array has it. So Collection can find this only at retrieval time and that too because of casting. So generics will ensure solving this issue.
– Kanagavelu Sugumar
Jun 8 '16 at 11:18