Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raw types and Generics -- Java [duplicate]

Tags:

java

generics

Possible Duplicate:
Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?
Java Generics — Assigning a list of subclass to a list of superclass

With raw types you can easily say something like this.

[...] // MyClass is generic with upper bound of Object

MyClass c = new MyClass<Double>();

[...]

But this isn't allowed

MyClass<Number> c = new MyClass<Double>() 

I don't understand why this is. My book tells me why the second doesn't work, because you can't add a Integer to a MyClass<Double>. What it doesn't explains is why MyClass<Double> is a subclass of MyClass<Object> (or the equivalent raw type form), since double is subclass of object.

So why is the first allowed if the second form isn't. Please realize I am new to this.

Edit: Taking it a step further what would happen in the first example if Number was the upper bound?

You can see here the effects of type erasure

class Untitled {
public static void main(String[] args) {

}
public static<T> void c(T t)
{
    t.SubClassMethod();// this won't work because class Object has no such method. But if I change the upperbound to SubClass it will.
            t.toString() // this will because class Object has such a method
}
}

My point is that why should it matter what the Generic is declared as if it ultimately becomes treated as the upper bound anyway?

like image 390
rubixibuc Avatar asked Mar 18 '12 23:03

rubixibuc


2 Answers

Try this:

MyClass<? extends Number> c = new MyClass<Double>();
like image 190
Bohemian Avatar answered Sep 23 '22 19:09

Bohemian


The first thing to eliminate your confusion is to understand that the Raw Type is not part of the generics system at all. It is in no way equivalent to Something<Object>. Basically, the reason the Raw Type exists at all is just for backward compatibility. When Generics were introduced in Java 5, some existing classes and interfaces were retroactively made generic. In order for old code that didn't have generic declarations to compile in the Java 5 or later compiler, the Raw Declarations are legal.

Any comparison between the way the Raw Type behaves and the way the Parameterized type behaves is in a way a bit fundamentally spurious. The intent of the design is not that the Raw Type be considered an 'alternative' to declaring a parameter. New code that uses the Raw Type is incorrect code. It's legal to compile it so that old code still works.

My point is that why should it matter what the Generic is declared as if it ultimately becomes treated as the upper bound anyway?

Because the entire point of the generics is to prevent ClassCastException. It will be treated as the actual declared type when someone, for example, someone takes the object back out of the list and assigns it to the specific type they're expecting. The compiler is making a promise that it guarantees this will succeed, so it has to restrict what goes in and out.

like image 45
Affe Avatar answered Sep 23 '22 19:09

Affe