why does this compile without any unchecked type warnings?

generics, java

Solution

In both of the statements, the compiler does not have enough information to infer the type argument for `V`. When this happens, it defaults to `V`'s upper bound, which is `Object`.

The assignments are valid because both `5` and `"a string"` are assignable to `Object`.

We can show that the type of `A.create().v` is `Object` by trying to assign it to a more specific type:

Integer i = A.create().v; // Type mismatch: cannot convert from Object to Integer

The error is the same, even if we assign a more specific type first (the result of an assignment expression is the type of the assigned variable):

Integer i = (A.create().v = 5); // same error

Note that a "type witness" can be used to explicitly specify generic type arguments, in the case that they aren't inferred:

Integer i = A.<Integer>create().v; // valid

A.<String>create().v = 5;           // incompatible types
A.<Integer>create().v = "a string"; //

These are contrived examples just to demonstrate compiler behavior, but a type witness is occasionally useful, for example:

static void m(List<String> list) { }

public static void main(String args[]) {

    m(Collections.emptyList());         // error
    m(Collections.<String>emptyList()); // valid
}

Problem

Why does the following code compile cleanly without any warnings, even with `xlint:all` ? ``` class A<V> { public V v; public <V> A() { } public static <V> A<V> create() { return new A<V>(); } } public class FooMain { public static void main(String args[]) { A.create().v = 5; A.create().v = "a string"; } } ``` running: ``` javac -Xlint:all src/FooMain.java ``` results in a clean compile without any warnings (unchecked, etc.). What is the type parametrization of the instance of the generic class `A` that gets's created on the first line and what on the second? And how does the compiler determine the type? By looking at the type of the r-values?

Original source