Reputation: 37655
Consider this example:
public final class Main<T extends Main<T>> {
public static void main(String[] args) {
Main<?> main = new Main<>();
}
}
This compiles perfectly. However when I try to make this compile without using the diamond, the only way I can get it to work is by using a raw type.
Main<?> main = new Main();
Attempts without raw types don't work:
Main<?> main = new Main<?>(); // None of
Main<?> main = new Main<Main<?>>(); // these
Main<?> main = new Main<Main<Main<?>>>(); // compile
So why does the original version with the diamond work? What is the inferred type when you write Main<?> main = new Main<>();
?
Is it inferring a raw type, or is it inferring some kind of infinitely nested type like this?
Main<Main<Main<Main<...>>>>
Upvotes: 15
Views: 1472
Reputation: 122489
It's possible to make something that compiles without the diamond operator, by using a generic helper method (but of course, this then begs the question, what type argument is being inferred for the call to the helper method):
final class Main<T extends Main<T>> {
public static void main(String[] args) {
Main<?> main = helper();
}
private static <T extends Main<T>> Main<T> helper() {
return new Main<T>();
}
}
Upvotes: 1
Reputation: 887767
The ?
in Main<?>
is a placeholder that may be any type at bind-time.
Each ?
that you write in source may be a different type (referred to in error messages as capture#2-of ?
), so you cannot assign an expression of Main<?>
to a variable of any expressible type.
The diamond operator works here because its type inference runs after the ?
s are captured – your Main<>
becomes not Main<?>
but Main<capture#1 of ?>
(assuming the Main<?>
you assign it to is capture#1
).
In other words, the diamond operator is the only syntax that can directly specify a specific capture, just like var
in C# is the only syntax that can directly specify an anonymous type. (note that overload resolution with method type inference can also resolve to specific captures)
As for what the code means, new Main<?>()
(for any capture of ?
) is shorthand for Main<? extends Object>
, or, in your case, Main<? extends Main<same ?>>
(the compiler automatically constrains the ?
to the constraints of the type). This becomes a covariant view of Main<>
, where the type parameter is convertible only to Main<?>
(since it may actually be any type, so you can't assume anything beyond the constraint).
Usually, there is no reason to actually create such a thing.
Upvotes: 4