Search code examples
javagenericsraw-types

Can we use raw types for <T extends SomeClass>?


It is a reply for the affirmation of the answer for "What is a raw type and why shouldn't we use it?", that say:

... In summary, raw types should NEVER be used in new code. You should always use parameterized types. ...

I didn't agree yet, that "you should NEVER use raw type". I think there are cases that you can use it safely.

For me there are three kind of raw type:

  1. "raw type": A raw instance of every class that have this assignment: class Foo <T>. Ex: Foo foo = new Foo()

  2. "raw type with extends": A raw instance of every class that have this assingment: class Foo <T extends SomeClass>. Ex: Foo foo = new Foo()

  3. "raw type with extends multi bounds": A raw instance of every class that have this assingment: class Foo <T extends SomeClass & SomeInterface1 & SomeInterface2>. Ex: Foo foo = new Foo()

The second one is the class that I think could be used safely (class Foo <T extends SomeClass>). And I would like to know if someone see any problem about it.

Example:

public class Tests {
    public static void main(String... args){
        GenericClass<SomeClassWithSomeInterface> genericClass1 = new GenericClass<>();
        genericClass1.set(new SomeClassWithSomeInterface());
        genericClass1.set(new SomeExtendClass());
        genericClass1.set(new Object()); // Compile-time error: type is safe

        GenericClass genericClass2 = new GenericClass<>();
        genericClass2.set(new SomeClassWithSomeInterface());
        genericClass2.set(new SomeExtendClass());
        genericClass2.set(new Object()); // Compile-time error: type is safe too. Or not?

    }
}

class SomeClass{    
}

interface SomeInterface{
}

class SomeClassWithSomeInterface extends SomeClass implements SomeInterface{
}

class GenericClass<T extends SomeClassWithSomeInterface>{
    private T t;

    public void set(T t){
        this.t = t;
    }
}

class SomeExtendClass extends SomeClassWithSomeInterface{
}

In this example above, both genericClass1 object and genericClass2 are type safe. My understanding is correct?


Solution

  • Consider this:

    class SomeExtendingClass extends SomeClassWithSomeInterface {}
    class SomeOtherExtendingClass extends SomeClassWithSomeInterface {}
    
    class Test {
        public static void main() {
            GenericClass<SomeExtendingClass> generic1 = new GenericClass<SomeExtendingClass>();
            generic1.set(new SomeExtendingClass()); // ok
            generic1.set(new SomeOtherExtendingClass()); // error (as expected)
    
            GenericClass generic2 = new GenericClass<SomeExtendingClass>();
            generic2.set(new SomeExtendingClass()); // ok
            generic2.set(new SomeOtherExtendingClass()); // ok (but shouldn't be!)
        }
    }