javac confused by generics on class?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Jun 10 16:29:33 UTC 2025
I've replied here (and moved the thread in compiler-dev) -- please
follow up there if anything feels missing:
https://mail.openjdk.org/pipermail/compiler-dev/2025-June/030756.html
Maurizio
On 10/06/2025 17:20, Éamonn McManus wrote:
> This question would probably be better asked on Stack Overflow or the
> like. The short answer is that the compiler is following the language
> spec. §4.8
> <https://docs.oracle.com/javase/specs/jls/se24/html/jls-4.html#jls-4.8> says:
>
> > The type of a constructor (§8.8
> <https://docs.oracle.com/javase/specs/jls/se24/html/jls-8.html#jls-8.8>),
> instance method (§8.4
> <https://docs.oracle.com/javase/specs/jls/se24/html/jls-8.html#jls-8.4>,
> §9.4
> <https://docs.oracle.com/javase/specs/jls/se24/html/jls-9.html#jls-9.4>),
> or non-|static| field (§8.3
> <https://docs.oracle.com/javase/specs/jls/se24/html/jls-8.html#jls-8.3>)
> of a raw type C that is not inherited from its superclasses or
> superinterfaces is the erasure of its type in the generic class or
> interface C.
>
> It /doesn't/ say that this only applies when the original type
> references the type parameters that have been omitted from the raw
> type. So the return type of getValues() in the raw Child is raw List,
> even though the original type List<String> doesn't mention T.
>
> On Tue, 10 Jun 2025 at 08:50, Jean-Noël Rouvignac
> <jean-noel.rouvignac at pingidentity.com> wrote:
>
> Hello,
>
> When doing refactorings to take advantage of newer Java features,
> I hit a new and weird edge case. I trimmed down the code several
> times, and ended up with the following tiny reproducer, and I
> don't understand what javac is complaining about even with javac 24:
>
> (Note: unlike the original code, this reproducer is very
> contrived, so there's no need to make comments on how bad it is: I
> fully agree)
>
> ```java
> 1 import java.util.ArrayList;
> import java.util.List;
> import java.util.stream.Collectors;
>
> public class Main {
> private static final class Child<T> {
> public List<String> getValues() {
> return new ArrayList<>();
> }
> }
>
> @SuppressWarnings("unchecked")
> private static String getString1(Child c) {
> // Compilation error:
> // Main.java:16: error: incompatible types: Object cannot
> be converted to String
> return c.getValues().stream().collect(Collectors.joining());
> }
>
> private static String getString2(Child c) {
> // Compilation error:
> // Main.java:27: warning: [unchecked] unchecked conversion
> // List<String> values = c.getValues();
> // ^
> // required: List<String>
> // found: List
> //1 warning
> List<String> values = c.getValues();
> return values.stream().collect(Collectors.joining());
> }
> }
> ```
>
> It turns out IntelliJ is a bit more eloquent than javac, and when
> hovering over the warning on `c.getValues()` at the line with
> `List<String> values = c.getValues();`, it reports the following:
>
> > Unchecked assignment: 'java.util.List' to
> 'java.util.List<java.lang.String>'. Reason: 'c' has raw type, so
> result of getValues is erased
>
> Is it possible that javac is doing early type erasure when
> analysing this code, erasing a bit too much? Even if the code uses
> `Child` without type argument, I would expect the return type of
> `getValues()` to be well defined as `List<String>`?
>
> What do you think?
> I am sure there is some rational explanation that I missed for
> this behaviour. I could not find a JBS issue showing the same case
> as here.
>
> Thank you,
> Jean-Noël Rouvignac
>
> /CONFIDENTIALITY NOTICE: This email may contain confidential and
> privileged material for the sole use of the intended recipient(s).
> Any review, use, distribution or disclosure by others is strictly
> prohibited. If you have received this communication in error,
> please notify the sender immediately by e-mail and delete the
> message and any file attachments from your computer. Thank you./
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20250610/1cf67bf6/attachment-0001.htm>
More information about the core-libs-dev
mailing list