[Run-time Get template class type] Java reflection mechanism + type erase mechanism

Source: Internet
Author: User
Tags class definition

Given a class with template parameters

Class a<t>

{

}

How do I get the type of T at run time?

In C #, this is simple, and the CLR's reflection mechanism is supported by the interpreter, presumably with the following code:

Namespace testreflect{    class program<t>    {public        Type Gettclass ()        {            type type= this. GetType ();             Type[] TTS = type. GetGenericArguments ();            return tts[0];}}    
In Java, however, the answer is no, there is no direct way to get t.class in Java. (At least JDK 1.7 was not possible before)

The root cause is that the Java language supports reflection, but the JVM does not support it because the JVM has the "type Erasure" attribute, which is "types erase".

But Java has no way to go, we can still use other methods to achieve our needs.

Method 1. The actual category is passed in through the constructor function. "Some people say that this method is not handsome, but it is undeniable that this method does not use reflection, but the most efficient, the reflection itself is not efficient." 】

public class a<t>{    private final class<t> clazz;    Public a<t> (class<t> clazz)    {        this.clazz = clazz;    }    Use Clazz on here}

Method 2. By inheriting this class, pass in the actual class that the template T corresponds to: (defined as an abstract class)

Class a<t>{public class Gettclass (int index) {   type gentype = GetClass (). Getgenericsuperclass (); &nbs         P if (! (        Gentype instanceof Parameterizedtype)    {      return object.class;   }   <span style= "White-space:pre" ></span> type[] params = ((Parameterizedtype) gentype). Getactualtypearguments (); <span style= "White-space:pre" ></span> if (index >= params.length | | Index < 0) {    <span style= "White-space:pre" ></span> <span style= "White-space:pre" ></span >throw new RuntimeException ("Index Out of Bounds")  <span style= "White-space:pre" ></span>}   <span style= "White-space:pre" ></span> if (! ( Params[index] instanceof Class)) {   <span style= "White-space:pre" ></span> return object.class;   <span style= "White-space:pre" ></span>}   <span style= "white-sPace:pre "></span> return (Class) Params[index]; }}

Inheriting classes:

public class B extends a<string> {public static void main (string[] args) {  b bb =new b ();          Bb.gettclass ();//That is the answer}}


I believe a lot of people have used code like this, but not everyone really understands why it is possible to do so.

Just look at the code:

We can

Getgenericsuperclass ();

But not:

Getgenericclass ();

Why is it?

There is a foreigner on the StackOverflow said:in Java If a class inherits another class with a template parameter, the template parameter is not erased by type. In a single class, its generic parameters are erased.

The first explanation is that this assumption is wrong . I believe that JCP will not be baffled by this unreasonable rule. If this argument is true, it is equal to:

public class C<t> {}public class c1<t> extends C<t>{public C1 () {} public class Gettclass (int index) {
   type Gentype = GetClass (). Getgenericsuperclass ();    if (! ( Gentype instanceof Parameterizedtype)   {      return object.class;  }    Type[] params = ((Parameterizedtype) gentype). Getactualtypearguments ();    if (Index >= params.length | | Index < 0) {     throw new RuntimeException ("Index outof Bounds");  }    if (! ( Params[index] instanceof Class) {     return object.class;  }      Return (Class) Params[index]; }}
After you call C1 directly to create the entity:

public static void Main (String[]args) {c1<d> a= new c1<d> (); System.out.println (A.gettclass (0));}

Can output: D

But the reality is, there is no output d, and the output is Object.

It doesn't matter if this is a subclass of the parent class.

So what exactly is the cause, a generic class (a class that contains template parameters) that does not resemble getgenericarguments () in C # What about the Getgenericclass () function?

Then, review the category "Type Erase" in Java.

I define it in my own language (not necessarily accurate, but for the same reason):

All of the generic parameters in Java are erased at compile time in code other than the "class declaration area" (partition below).

public class/interface [class declaration area] classname{[class definition area]}

The following 2 classes:

public class E<t>{public static void Main (String []args) {list<string> a = new arraylist<string> (); System.out.println ("Done");}} Class Sube extends e<string>{}

The compiled class file code is: (by Java De-compiler)

public class e<t>{public  static void Main (string[] args)  {    List a = new ArrayList ();//difference in this line    Syst Em.out.println ("Done");}  }
Class Sube extends e<string>{}
As you can see, my so-called "class declaration area" is identical to the Java file.

All of the generic parameters in the class definition area are removed.

So why is that?

This involves the Java language features, the JDK starting from 1.5 (should be) to support generics, but only the Java syntax Support generics, the JVM does not support generics, many people laugh to call it "false generics."

In fact, I personally think that this may be the Java language is all objects, and requires a high degree of polymorphism, highly oriented to abstract programming, the characteristics of the weak type foreshadowing.

For example list, since as a set, why should care about its specific elements are consistent, the first to put white, the second to put blacks, the third put yellow people ... This is better.

So when we use

List<string>, the compiler sees not a String, but an object (all types in Java inherit from object).

Once the generic parameter in the class definition area is erased. Then using this template class to create an instance, when run, the JVM reflection is unable to get the specific type of this template.

So

similar to GetGenericArguments () in C # The Getgenericclass () function is meaningless in Java.

The meaningless point here is based on the Java and JVM features described above. (If the JVM supports true generics, then all this will make sense)

Why does he mean nothing to disprove the law:

Assuming this function exists and makes sense, the following code can get T.class

Class A<t>{Public  Class Gettclass ()   {      return this.getgenericclasses () [0];//there is only one template parameter  } Public  static void main (String []args)  {  a<integer> a= new a<integer> ();  System.out.print (A.gettclass ());}  }
Such a piece of code will be compiled into:

Class A<t>{Public  Class Gettclass ()   {      return this.getgenericclasses () [0];//there is only one template parameter  } Public  static void main (String []args)  {  A a= new A ();  System.out.print (A.gettclass ());}  }

This is the problem, the JVM executes the. class file, not the. java file, and in the JVM's opinion, the class file doesn't say anything about T, and now you're asking me what I need to get you, T.class?

So

Getgenericclasses ()

This function always returns JAVA.LANG.OBJECT. Equals no return.

So there is no need for this function to exist.

To think back, the reason why

Getgenericsuperclass (); Effective, its essence lies in

The class declaration area in the subclass's Java file specifies the true class of T.

Such as:

public class B extends a<integer>{

//...

}



Such a small unsolved case is clear.













[Run-time Get template class type] Java reflection mechanism + type erase mechanism

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.