1

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?

Community
  • 1
  • 1
Paulo
  • 2,956
  • 3
  • 20
  • 30
  • 2
    It's possible to use them *correctly* (in a way that doesn't lead to type confusion), but I wouldn't call it *safely*. "Safe" implies the compiler is preventing you making mistakes, which it isn't here. – user253751 Apr 10 '15 at 23:12
  • So, this is my question. The second one "raw types with extends" is safe? because the compile is preventing me making mistakes. – Paulo Apr 10 '15 at 23:14
  • The point of making the class generic is to be able to restrict what it accepts to a subclass of the upper bound (i.e. to SomeExtendClass for example). Using a raw type won't prevent you from adding an instance of SomeClassWithSomeInterface to a GenericClass that is supposed to contain a SomeExtendClass. – JB Nizet Apr 10 '15 at 23:15

1 Answers1

4

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!)
    }
}
user253751
  • 57,427
  • 7
  • 48
  • 90
  • Why shouldn't be? I think that we can use this approach for all subtypes of SomeClassWithSomeInterface – Paulo Apr 10 '15 at 23:29
  • 1
    @Paulo Because, as the first part of the main method shows, the goal is to have a GenericClass instance that only accepts SomeExtendingClass. Using a raw type makes that impossible. – JB Nizet Apr 10 '15 at 23:33
  • @JBNizet the first part of the main method say "this generic can accept all instances or sub instances of SomeExtendingClass".. The second part say:" this generic can accept all instance and sub instance of SomeClassWithSomeInterface". For me the type is safe yet. – Paulo Apr 10 '15 at 23:59
  • When you are omitting the type, this generic assume that it is a generic of SomeClassWithSomeInterface – Paulo Apr 11 '15 at 00:01
  • 1
    @Paulo: no. The first one says "this generic can accept all instances or sub instances of SomeExtendingClass". The second one says "I haven't noticed this class was generic and I'm using it as a raw type. Let the poor maintainer guess what my intention is and what this list is supposed to contain". Why would you make a special case for the case where the concrete type is the upper bound? – JB Nizet Apr 11 '15 at 00:07
  • Oops! I made a mistake in the code so it doesn't demonstrate my point, I think. – user253751 Apr 11 '15 at 02:04
  • @immibis Thanks. Now I can understand that this raw generic type is not safe. – Paulo Apr 11 '15 at 02:11