Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Wednesday, February 10, 2016

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 c = new Cat(); // Compiler error      

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 c1 = new Cat();  Cat c2 = c1; // error      

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, abg Pbzcnenoyr. 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 foo = new Foo();  Integer i = foo.bar(1);    //compiles  Foo foo = new Foo();  Integer i = foo.bar(1);    // fails  Foo foo = new Foo();  Integer i = foo.bar(1); // error: Object cannot be converted to Integer      

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 become Cat

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

Popular Posts

Powered by Blogger.