Why the return value of java generic (class) method is Object??

as far as I know, java virtual machines don"t recognize generic classes or generic methods, so when compiled into bytecode, all generic classes or generic methods are converted to normal classes or methods.

for example:

// 
class Test<T> {
    public T res = null;
    
    public Test(T res){
        this.res = res;
    }
    
    public T get(){
        return this.res;
    }
}

Test t = new Test<String>("-Test-get");
// 
String res = t.get();

Type parameters are replaced at compile time (type erasure), that is, the code in the compiled bytecode should be as follows:

public class Test {
    private String res = null;
    
    public Test(String res){
        this.res = res;
    }
    
    public String get(){
        return this.res;
    }
}

Test t = new Test("-Test-get");
// :Object ?
String t = t.get();

the problem lies in:

Test t = new Test<String>();
//  Object
String res = t.get();

I am very depressed. cannot understand why a method call after providing a type parameter returns not the supplied type String but the Object type?

however, in the following scenario, the result is correct

// 
Test<String> t = new Test<>();
String res = t.get();

Why is this?

Nov.15,2021

Test t is equivalent to Test < Object > t, and the return expectation is Object, but it is actually String, so you just need to add a cast, that is,

String res = (String)t.get();

generics are meant to be used in declaration.

Test<String> t = new Test<>();

this way the compiler knows that the t reference is a Test reference with String generics.

Test t = new Test<String>();

the compiler only knows that the reference t points to an object with String generics.
but I don't know that t is generic.
and you t.get () this method is the method called by the t reference.
the latter way of writing the compiler does not know that your reference is with generics. The default is the Object type.


Object is the base class of everything, and all classes are Object, reflections. Using Object, ensures versatility.
when you actually use it, you need to judge and convert the type based on reflection.
carry out forced conversion with confidence, or you can first judge whether (instanceof), is more based on the actual business to encapsulate the corresponding tool classes


you can refer to these two questions to think about why the current behavior is reasonable.

question 1: can the following code be compiled?
(yes, because ArrayList < String > and ArrayList < Integer > are both List).

        if (input == 42) {
            list = new ArrayList<String>();
            list.add("magic").
        } else {
            list = new ArrayList<Integer>();
            list.add(42).
        }
        
        // 
        // Object value = list.get(0);
        // String value = list.get(0);
        // Integer value = list.get(0);
  • The problem of JAVA8 getting generic types

    ask a question about generics: like the interface with generics below public interface AAA<C,M,S> {} public interface BBB<T extends Number> extends AAA<T,String,Boolean> {} public interface CCC extends BBB<Integer> {} public...

    Mar.16,2022
Menu