Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does this compile without any unchecked type warnings?

Tags:

java

generics

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?

like image 450
Marcus Junius Brutus Avatar asked Feb 04 '14 20:02

Marcus Junius Brutus


People also ask

What are unchecked warnings?

An unchecked warning tells a programmer that a cast may cause a program to throw an exception somewhere else.

How do I fix unchecked unchecked cast?

If we can't eliminate the “unchecked cast” warning and we're sure that the code provoking the warning is typesafe, we can suppress the warning using the SuppressWarnings(“unchecked”) annotation. When we use the @SuppressWarning(“unchecked”) annotation, we should always put it on the smallest scope possible.

What does unchecked assignment mean in java?

What does unchecked assignment mean? Unchecked assignment: 'java.util.List' to 'java.util.List<java.lang.String>' It means that you try to assign not type safe object to a type safe variable.


2 Answers

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
}
like image 161
Paul Bellora Avatar answered Sep 21 '22 21:09

Paul Bellora


Due to these two statement

A.create().v = 5;
A.create().v = "a string";

Compiler will easily resolve in the first case <V> by <Integer>

and in the second case <V> by <String>

like image 36
Girish Avatar answered Sep 19 '22 21:09

Girish