javac confused by generics on class?
Archie Cobbs
archie.cobbs at gmail.com
Tue Jun 10 16:07:30 UTC 2025
Following up on what Maurizio said. There is an important difference
between Foo and Foo<?>. The use of raw type like Foo "rawifies" all the
methods in class Foo.
Here's a simpler reproducer:
import java.net.http.HttpResponse;
import java.util.Optional;
import javax.net.ssl.SSLSession;
public class Main2 {
void m1(HttpResponse r) {
Optional<SSLSession> s = r.sslSession(); // unchecked warning here
}
void m2(HttpResponse<?> r) {
Optional<SSLSession> s = r.sslSession(); // no warning here
}
}
See also this stackoverflow answer
<https://stackoverflow.com/a/11007894/263801>.
-Archie
On Tue, Jun 10, 2025 at 10:51 AM 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.*
--
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20250610/a027e737/attachment-0001.htm>
More information about the compiler-dev
mailing list