Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does erasure still allow overriding/implementation?

At first glance I thought the following makes sense:

interface Test<T> {
    T getValue(T n);
}

class Impl implements Test<Integer>{
    public Integer getValue(Integer n){
        return n;
    }
}

And it compiles properly so everything seems A-OK.

But then I thought about it some more, in the context of erasure, and it seems to me that the Test interface gets erased to this:

interface Test {
    Object getValue(Object n);
}

So how is Impl still able to implement Test?

like image 381
kng Avatar asked Jul 25 '20 00:07

kng


People also ask

What is erasure Why is erasure important in Java generics implementation?

Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.

Is it mandatory to use @override?

While it is not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with @Override fails to correctly override a method in one of its superclasses, the compiler generates an error.

Why overriding is useful?

The benefit of overriding is: ability to define a behavior that's specific to the subclass type, which means a subclass can implement a parent class method based on its requirement. In object-oriented terms, overriding means to override the functionality of an existing method.

What is type erasure and why do we need it?

What Is Type Erasure? Type erasure can be explained as the process of enforcing type constraints only at compile time and discarding the element type information at runtime. Therefore the compiler ensures type safety of our code and prevents runtime errors.


1 Answers

javac actually creates bridge methods for this:

class Impl implements Test<Integer>{
    @Override public Integer getValue(Integer n){
        return n;
    }
}

compiles to

class Impl implements Test {
    public Integer getValue(Integer n) { // overrides nothing!
        return n;
    }
    @Override @Synthetic @Bridge public Object getValue(Object n) { 
        return this.getValue((Integer)n);
    }
}

Note: Synthetic and Bridge are not real annotations, but the compiled class files do tag these methods as "synthetic" and "bridge".

By using these bridge methods, Java ensures that if you have an Impl, you can call Impl#getValue(Integer)Integer (if you know that it actually has type Impl), or you can call the "generic" Test#getValue(Object)Object, if you only know that it's a Test<?>.

like image 195
HTNW Avatar answered Oct 14 '22 00:10

HTNW