0

Since generics are invariant. The following code produces a compile time error incompatible types:

Stack<String> stackOfStrings = new Stack<String>();
Stack<Object> stackOfObjects = stackOfStrings;

Why then is the code below that produces an array of a stack of strings acceptable to the compiler and taught in textbooks such as Algorithms, 4th Edition by Robert Sedgwick and Kevin Wayne, pg. 158:

Stack<String>[] a = (Stack<String>) Stack[];

EDIT: the above snippet taken directly from the textbook is actually (sorry for the mistake):

Stack<String>[] a = (Stack<String>[]) new Stack[N];
8
  • 4
    I don't see the connection between the two snippets. Why if the first example produces an error, the second is, or isn't supposed to? Commented Mar 23, 2015 at 13:11
  • 6
    The second example doesn't even look like valid code to me... Commented Mar 23, 2015 at 13:13
  • Generics are not covariant, but arrays are. (Because of this arrays and generics don't work very well together). Commented Mar 23, 2015 at 13:15
  • I guess this question is a "comeback" on stackoverflow.com/questions/29209224/… Well, lets put it that way: who says that authors of books are never making mistakes? Meaning: yes, this code is possible; but again: it is not recommended to mix arrays in generics in Java. On the other hand, it would have made the type system inconsistent if the compiler would forbid such mixes. Commented Mar 23, 2015 at 13:15
  • If you write a syntactically correct statement, you get the error message. For example : (Stack<String>) new Stack[10];. Commented Mar 23, 2015 at 13:16

2 Answers 2

3

First issue: to solve this you could use Stack<? extends Object> stackOfObjects = stackOfStrings;. You have to tell the compiler subtypes are also allowed in the generic class.

Second: My compiler isn't allowing it.

Sign up to request clarification or add additional context in comments.

Comments

1

It is unclear what you are asking. You say that the first thing doesn't work and the second does, but make not obvious connection between the two.

Generics are invariant, meaning that Foo<A> and Foo<B> are not subtypes of one another, if A and B are different concrete types, even if there is a sub typing relationship between A and B.

I don't see that situation happening in the second example. It is possible to convert between the raw type Foo and Foo<A>. That's not converting from one parameter to another as in the first example.

2 Comments

I see that my question is confusing. I myself was a little confused when I wrote it. I had not really understood the concept of the raw type nor of the possibility of using the unbounded wildcard and thus the second line of code didn't make sense to me. Thanks!
The connection between parts one and two made sense to me because I'd thought the second fragment of code explicitly converted between two concrete types.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.