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