Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the base type not returned when no generic type specified? [duplicate]

I have a code like this:

public class A<T extends String> {

    T field;
    List<T> fields;

    public T getField() {
        return field;
    }

    public List<T> getFields() {
        return fields;
    }

    public static void test(){
        A a = new A();
        String s = a.getField();
        List<String> ss = a.getFields();
    }
}

Why when creating A with no generic type getFiled returns String but getFileds returns List<Object>?

I have to define A as A<String> a = new A<>() for this to work properly.

Thanks,

like image 262
MAREK Avatar asked Jun 29 '18 08:06

MAREK


1 Answers

The erasure of the type param T in the declaration T field is String, because T has bound:

<T extends String>

and any subtype of a String is also a String1.

But, this doesn't apply to generic List<T>. It stems from the fact that generics are not covariant:

List<String> str = new ArrayList<String>();
List<Object> obj = str; // Error: incompatible types (even though String extends Object)

The erasure of List<T> in the declaration List<T> fields is List, particularly because List<T> can hold a String or its subtypes1. And given that A is a raw type, compiler can't guess the type of the elements in the list returned by the getFields() method.

Anyway, this line of code:

List<T> fields;

is compiled (Erasure of Generic Types) into:

List fields;

As a result, when you write:

A a = new A();  instead of  A<String> a = new A<>();

you lose the type safety and get an "Unchecked assignment" warning - in this case, compiler can not guarantee that the fields list is exactly the List<String>:

List<String> list = a.getFields(); // Unchecked assignment: 'List' to 'List<String>' ...

P.S. Don't use raw types!


1 - As you know, String class is final and can't be extended. Replace it with any type that can be extended if you wish.

like image 126
Oleksandr Pyrohov Avatar answered Oct 13 '22 02:10

Oleksandr Pyrohov