简体   繁体   中英

Generic Type Erasure Warning

I have this code from the book Thinking in Java ,where Bruce indicates the warning on calling the method set() . The code is as follows:

    package testPackage;

    class GenericBase<T> {
    private T element;
    public void set(T arg) { arg = element; }
    public T get() { return element; }
    }
    class Derived1<T> extends GenericBase<T> {}
    class Derived2 extends GenericBase {} // No warning
    // class Derived3 extends GenericBase<?> {}
    // Strange error:
    // unexpected type found : ?
    // required: class or interface without bounds
    public class ErasureAndInheritance {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        Derived2 d2 = new Derived2();
        Object obj = d2.get();
        d2.set(obj); // Warning here!
        }
    }

If I remove the annotation, I get the following warning:
Type safety: The method set(Object) belongs to the raw type GenericBase. References to generic type GenericBase should be parameterized

My question is, Why is the warning displayed on the set() method? And can somebody please explain what this warning means?
Btw, I am completely new to Java Generics and although I read other questions on Generics, I am still somewhat confused on Erasure .

From the Java doc here

Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to:

  • Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
  • Insert type casts if necessary to preserve type safety.
  • Generate bridge methods to preserve polymorphism in extended generic types.
  • Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.

Simple: Every generic is a Object after the compile process, it just adds the casting for you, and if you did something wrong it will generate a compiler error.

About the unchecked annotation, it's used when the compiler can't be sure that what are you doing is correct (in fact, you use the raw type which is the same thing as GenericBase<Object> )

You have the warning since the set methods except the type T but since you are using a raw type, it don't know what T is, and generate this warning to let you know that you are using a raw type (bad thing).

You can use the annotations to say: "I know it's a raw type, but i know it's legal and i know what i'm doing".

Mixing raw types and generic types is possible due to the way that generics are implemented, as i said above, after the compiler process the T becomes Object and it means that a raw object like GenericBase is the same thing like GenericBase<T> .

The reason that it doesn't asks for any casting with generics, is because it will add the casts for you (and you can be sure that the code will always work in runtime without worry about a possible ClassCastException ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM