Are generic type parameters converted to Object for raw types?
Are generic type parameters converted to Object for raw types?
Consider this piece of code:
public class Main { public static void main(String[] args) { Cat cat = new Cat(); Integer i= cat.meow(); cat.var = 6; } } public class Cat { public E var; public E meow() { return null; } }
As per my understanding since I've not specified the type parameter on LHS, it would be taken as Object
. And Cat
should become Cat
because for the variable declaration to make any sense T must translate to a Class/Interface reference. Is this a correct understanding of how it works? How is type parameter T handled in case of raw types?
I've discussed this on chat and got following explanation which is way over my head:
Generics works because types are erased. Consider T an erasure of #0-capture-of-Object. When T isn't specified (rawtyped), it is #0-capture-of-(nothing)
What does #0-capture-of-(nothing)
mean?
Side note: since generic types are implemented as compile time transformations it would be easier to understand them if one could see the final translated code. Does anyone know a way to see the translated code (not byte code) for a class?
Answer by redge for Are generic type parameters converted to Object for raw types?
Generic types defined in objects like the
Cat c = new Cat();
are only intended to provide the compiler with the chance to check that the types will match at runtime.
Generic types assigned in class definitions are retained in the compiled class.
public class Cat{}
Or
public class Intcat extends Cat{}
The runtime knows that the generic argument is bound by Number in the first case and is Integer in the first case.
Answer by Kelo for Are generic type parameters converted to Object for raw types?
I have no links to back this up, but I'd rather assume that c
becomes raw type Cat
, not Cat
. Raw types don't handle parameter T, which is why they are prone to errors. javadoc says: A raw type is the name of a generic class or interface without any type arguments.
That chat log seems to mean exactly that, but in a confusing manner.
Answer by Svend Hansen for Are generic type parameters converted to Object for raw types?
This code is valid:
Cat c = new Cat();
c
is now of the Raw Type Cat
. This is not valid:
Cat
So, it's not exactly the same. Though you can, after the first line, do things like:
c.var = 5; System.out.println(c.var); c.var = 1; System.out.println(c.var); c.var = "test"; System.out.println(c.var);
Outputs:
5 1 test
Answer by Blip for Are generic type parameters converted to Object for raw types?
I actually Do not know How it is actually implemented in the bytecode But from my understanding Cat c = new Cat
Stores the new instance of Cat
created by new Cat
in the variable c
. Now if you query c
to know what is the type of var
it will reply Integer
and not Object
because the instance that was created has a type of Integer
.
Now If you execute c.var = "Text";
and query c to know what is the type of var
. It would reply String
. This does not means that by default it is converting
to Object
. It means that c
does not know what is the type of var
.
I feel that is why the wild card is used.
Cat c = new Cat
it would always convert
to Object
. That is the reason why it is always advised not the use raw types for generics.
Answer by Cephalopod for Are generic type parameters converted to Object for raw types?
No,
raw types are not as if they are paramterized with Object
, nor are they like wildcard types ().
For raw types, generics are turned off.
This code is compiles (with warnings):
Cat c1 = new Cat(); Cat c2 = c1;
This code does not:
Cat c1 = new Cat(); // btw: this is the same as Cat Cat c2 = c1; // error
neither does this:
Cat
As for the type of var
:
the type of the field after compilation is whatever the upper-bound of the parameter is (Object
if none is specified). But what does the compiler do if we access var
?
Cat c1 = ... String c1Var = c1.var;
This code compiles without error, but what the compiler will actually compile is this:
Cat c1 = ... String c1Var = (String) c1.var;
As you can see, var
is always treated as a field of type Object
, but with generics, the compiler automatically inserts type-safe casts. That's all. If you use raw types, you have to do it yourself. Either way, when you put a Cat
that stores an integer in a Cat
variable, you will only get a runtime exception if you try to read var
.
A quiz
Now look at the declaration of Collections.max. Why do you think the parameter is defined as T extends Object & Comparable
?
Answer encoded in rot13:
Fb gung nsgre pbzcvyngvba gur erghea glcr vf
Bowrpg
, abgPbzcnenoyr
. Guvf vf arrqrq sbe onpxjneqf pbzcngvovyvgl (gur zrgubq vgfrys vf byqre guna trarevpf).
Edit:
Here is another good example that I just stumbled upon:
class Foo { public V bar(V v) { return v; } } //compiles Foo
Using no parameters disables generics entirely.
Answer by hetec for Are generic type parameters converted to Object for raw types?
I think Cat c is a RAW type and could be considered as a "wildcard type" like Cat
. Since Cat
is the supertype of each type of Cat including Cat
, Cat c
may take a new Cat
object.
This is also mentioned here: Interoperating with Legacy Code
"Most people's first instinct is that Collection really means Collection. However, as we saw earlier, it isn't safe to pass a Collection in a place where a Collection is required. It's more accurate to say that the type Collection denotes a collection of some unknown type, just like Collection."
...
"So raw types are very much like wildcard types, but they are not typechecked as stringently. This is a deliberate design decision, to allow generics to interoperate with pre-existing legacy code."
Answer by Kshitiz Sharma for Are generic type parameters converted to Object for raw types?
@Cephalopod
has provided the correct answer, however I'd like to expand on that with some of my own explanation.
for the variable declaration to make any sense T must translate to a Class/Interface reference.
That is correct. Generics are a compile time transformation. Runtime system has no notion of abstract types. So before the class is loaded into memory the abstract type T must be replaced by an actual type reference.
Run the following code:
System.out.println(Cat.class.getMethod("meow").getReturnType()); System.out.println(Cat.class.getField("var").getType());
The output is:
class java.lang.Object class java.lang.Object
The formal type parameter E
has been replaced with Object
.
Cat
should becomeCat
Wrong. Cat
will stay Cat
. Why? Look at the decompiled class file for Main
:
public class Main { public static void main(String[] args) { Cat cat = new Cat(); Integer i = (Integer)cat.meow(); cat.var = Integer.valueOf(6); } }
The purpose of specifying formal type parameter with <>
is to enable compiler to generate explicit casts.
When you say new Cat()
it doesn't have to turn into anything, the compiler simply won't generate a cast and the method call would look like:
Integer i = cat.meow(); // No cast at all
Are generic type parameters converted to Object for raw types?
To clarify what is being asked here, the above questions means: Is E
replaced with java.lang.Object
if I don't specify anything when instantiating Cat
.
Actually E
would be replaced with java.lang.Object
even if you specified
when instantiating Cat
. The replacement/transformation is done at compile time while the instantiation is at runtime. How you use the type isn't going to change its class definition.
Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72
0 comments:
Post a Comment