8
Set<Object> removedObjs = new HashSet<>();
List<? extends MyEntity> delObjs = (List<? extends MyEntity>) new ArrayList<>(removedObjs);

MyEntity is marker interface.

Above code is working fine in (java version "1.7.0_91", to be precise) but not in (java version "1.8.0_77")

In Java8, I am getting the following exception:

incompatible types: ArrayList<Object> cannot be converted to List< ? extends MyEntity>

4
  • 4
    If you remove the <> you should get just a warning. If it doesn't work in Java 8, then it probably shouldn't have worked in Java 7. Commented May 16, 2016 at 8:18
  • It can be compiler in my environment JAVA1.8.0_92 in eclipse with only warning:Type safety: Unchecked cast from ArrayList<Object> to List<? extends MyEntity> but cannot javac Commented May 16, 2016 at 8:48
  • 3
    Looking at the code, it seems logical that it shouldn't work. just insert a removedObjs.add("42"); between the two lines to see why. Commented May 16, 2016 at 10:50
  • 1
    Any chance of improving the title to make it more useful to people searching for this issue in future? Commented May 16, 2016 at 15:21

2 Answers 2

11

Your code should neither work in Java 7 nor in Java 8, because you are trying to cast an ArrayList<Object> (type returned from the constructor) to a List<? extends MyEntity> and it has no sense even at compile time (see this question). That's why the compiler is complaining.

The following code will compile:

Set<Object> removedObjs = new HashSet<>();
List<? extends Integer> delObjs = (List) new ArrayList<>(removedObjs);

However, the compiler will throw a warning since you are performing an unsafe conversion.

EDIT: As @Tom points out:

"Your code should not work in java 7" It shouldn't, but it worked, because the compiler checks were still a bit faulty in that version. This has been fixed in Java 8, that is why it now fails.

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

4 Comments

"Your code should not work in java 7" It shouldn't, but it worked, because the compiler checks were still a bit faulty in that version. This has been fixed in Java 8, that is why it now fails. (just a note)
^ this should be added to the answer.
@Tom: I don’t have a jdk1.7.0_91 at hand, but I tested with jdk1.7.0_13, jdk1.7.0_40, jdk1.7.0_51, jdk1.7.0_80, and Eclipse (with Java7 conformity). None of them accepted the code of the question.
The Java Language Specification discourages the use of raw types except for working with legacy code predating generics. See also stackoverflow.com/questions/2770321/…
8

Java 8 changed a lot about type inference and related subjects. As such, it's not surprising if some edge cases (such as shady casts) suddenly become invalid.

Whatever the reason is, you can still cast your list, but it's slightly more ugly than before:

(List<? extends MyEntity>) (List) new ArrayList<>(removedObjs);

As pointed out by Peter Lawrey's comment, this can be written even shorter as

(List) new ArrayList<>(removedObjs);

1 Comment

The Java Language Specification discourages the use of raw types except for working with legacy code predating generics. See also stackoverflow.com/questions/2770321/…

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.