Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invocation of java generic method

Tags:

java

generics

Given the generic method:

<T> List<T> getGenericList(int i) {...}

the following code compiles without any warning:

public List<String> getStringList(boolean b){
    if(b)
        return getGenericList(0);
    else
        return getGenericList(1);
}

but this one generates 'Type mismatch' compilation error:

public List<String> getStringList(boolean b) {
    return (b) ? getGenericList(0) : getGenericList(1);
}

Why?

like image 400
Gennady Shumakher Avatar asked Jun 30 '11 13:06

Gennady Shumakher


1 Answers

This is NOT a generics problem, but a consequence of the way the compiler has to infer the type of the ternary expression.

It happens the same with this equivalent code. This code works:

public byte function(boolean b){
    if(b)
        return 1;
    else
        return 2;
}

While this doesn't:

public byte function(boolean b) {
    return (b) ? 1 : 2;
}

The reason is that when the compiler tries infer the type of this expression

    return (b) ? 1 : 2;

It first has to obtain the type of each one of the operands, and check if they are compatible (reference) to evaluate wether the ternary expression is valid or not. If the type of the "return" were propagated to automatically cast or promote each one of the operands, it could lead to resolve the type of a ternary expression differently depending on the context of this expression.

Given that the type of the "return" cannot be propagated to the operands, then in the menctioned case:

    return (b) ? getGenericList(0) : getGenericList(1);

the binding of the generic type cannot be done, so the type of each one of the operands is resolved to List<Object>. Then the compiler concludes that the type of the whole expression is List<Object>, which cannot be automatically casted to List<Integer> (because they are not compatible types).

Whereas this other one

    return getGenericList(0);

It applyes the type of the "return" to bind the generic type T, so the compiler concludes that the expression has a List<String> type, that can be returned safely.

like image 141
Mr.Eddart Avatar answered Nov 12 '22 17:11

Mr.Eddart