Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self-referential Generic Types

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<...>>>>
like image 414
Paul Boddington Avatar asked Nov 05 '15 00:11

Paul Boddington


People also ask

What is self referential class in Java?

A self-referential class contains an instance variable that refers to another object of the same class type.

What is self reference in C#?

Self-referencing table in entity framework means in order to store some hierarchical data you can say that a self referencing table is a table where the primary key (PK) of a table is also known a foreign key.

What is generic type of data?

Definition: “A generic type is a generic class or interface that is parameterized over types.” Essentially, generic types allow you to write a general, generic class (or method) that works with different types, allowing for code re-use.


1 Answers

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.

like image 127
SLaks Avatar answered Sep 21 '22 01:09

SLaks