A detailed explanation of Java reflection mechanism and example code _java

Source: Internet
Author: User
Tags array length modifier null null reflection

Java Reflection detailed

This article is still using a small example to illustrate, because I always feel that the case driven is the best, or only to see the theory, read also do not understand, but suggest that after reading the article, in retrospect to look at the theory, will have a better understanding.

Start the text below.

Case 1 Gets the complete package name and class name from an object

package reflect;
 
/**
 * Obtains the complete package name and class name * * * * * * * * * * * * * * * * */class
demo{
  //other codes
 
through an object Class hello{public
  static void Main (string[] args) {
    demo demo=new demo ();
    System.out.println (Demo.getclass (). GetName ());
  }

"Run Results": Reflect.demo

Add a sentence: All class objects are actually instances of class.

Case 2 Instantiating the Class class object

package reflect;
Class demo{
  //other codes ...
}
 
Class hello{public
  static void Main (string[] args) {
    class<?> demo1=null;
    Class<?> Demo2=null;
    Class<?> Demo3=null;
    try{
      //generally try to use this form
      demo1=class.forname ("Reflect.demo");
    } catch (Exception e) {
      e.printstacktrace ();
    }
    Demo2=new Demo (). GetClass ();
    Demo3=demo.class;
     
    System.out.println ("Class name  " +demo1.getname ());
    System.out.println ("Class name  " +demo2.getname ());
    System.out.println (class name  +demo3.getname ());
     
  }

"Run Results":

Class name Reflect.demo

Class name Reflect.demo

Class name Reflect.demo

Case 3 instantiating objects of other classes by class

Instantiating an object through an parameterless construct

 package reflect;
  Class person{public String getName () {return name;
  public void SetName (String name) {this.name = name;
  public int getage () {return age;
  public void Setage (int age) {this.age = age;
  @Override public String toString () {return "[" +this.name+ "" +this.age+ "]";
  private String name;
private int age;
    Class hello{public static void Main (string[] args) {class<?> demo=null;
    try{demo=class.forname ("Reflect.person");
    }catch (Exception e) {e.printstacktrace ();
    Person Per=null;
    try {per= (person) demo.newinstance ();
    catch (Instantiationexception e) {//TODO auto-generated catch block E.printstacktrace ();
    catch (Illegalaccessexception e) {//TODO auto-generated catch block E.printstacktrace ();
    } per.setname ("Rollen");
    Per.setage (20);
  System.out.println (per); }
}

"Run Results":

[Rollen 20]

But note that when we cancel the default parameterless constructor in person, such as defining a constructor that has only one parameter, an error occurs:

For example, I define a constructor:

Public person (String name, int age) {
    this.age=age;
    This.name=name;
  }

Then continue running the above program, and it will appear:

Java.lang.InstantiationException:Reflect.Person

At Java.lang.Class.newInstance0 (class.java:340)

At Java.lang.Class.newInstance (class.java:308)

At Reflect.hello.main (hello.java:39)

Exception in thread "main" java.lang.NullPointerException

At Reflect.hello.main (hello.java:47)

So when you write an object that uses class to instantiate another class, be sure to define the parameterless constructor yourself.

"Case" calls constructors in other classes through class (or you can create objects of other classes through class in this way)

package reflect;
 
Import Java.lang.reflect.Constructor;
  Class person{Public person () {} public person (String name) {this.name=name;
  (int age) {this.age=age;
    Public person (String name, int age) {this.age=age;
  This.name=name;
  Public String GetName () {return name;
  public int getage () {return age;
  @Override public String toString () {return "[" +this.name+ "" +this.age+ "]";
  private String name;
private int age;
    Class hello{public static void Main (string[] args) {class&lt;?&gt; demo=null;
    try{demo=class.forname ("Reflect.person");
    }catch (Exception e) {e.printstacktrace ();
    Person Per1=null;
    Person Per2=null;
    Person Per3=null;
    Person Per4=null;
    Get all the constructors constructor&lt;?&gt; cons[]=demo.getconstructors ();
      try{per1= (person) cons[0].newinstance ();
      per2= (person) cons[1].newinstance ("Rollen"); per3= (person) conS[2].newinstance (20);
    per4= (person) cons[3].newinstance ("Rollen", 20);
    }catch (Exception e) {e.printstacktrace ();
    } System.out.println (Per1);
    System.out.println (PER2);
    System.out.println (PER3);
  System.out.println (PER4);
 }
}

"Run Results":

[NULL 0]

[Rollen 0]

[NULL 20]

[Rollen 20]

Case

Returns the interface implemented by a class:

package reflect;
  Interface china{public static final String name= "Rollen";
  public static int age=20;
  public void Saychina ();
public void SayHello (String name, int age);
  Class person implements china{public person () {} public person (String sex) {this.sex=sex;
  Public String Getsex () {return sex;
  } public void Setsex (String sex) {this.sex = sex;
  @Override public void Saychina () {System.out.println ("Hello,");
  @Override public void SayHello (String name, int age) {System.out.println (name+ "" +age);
Private String sex;
    Class hello{public static void Main (string[] args) {class&lt;?&gt; demo=null;
    try{demo=class.forname ("Reflect.person");
    }catch (Exception e) {e.printstacktrace ();
    //Save all the Interfaces class&lt;?&gt; intes[]=demo.getinterfaces ();
    for (int i = 0; i &lt; intes.length i++) {SYSTEM.OUT.PRINTLN ("implemented Interface" +intes[i].getname ());
 }
  }
}

"Run Results":

Implementation of the interface Reflect.china

(Note that the following examples will use the person class for this example, so to save space, the code part of the person is no longer pasted, just the code for the main class hello)

"Case": getting the parent class in another class

Class hello{public
  static void Main (string[] args) {
    class<?> demo=null;
    try{
      demo=class.forname ("Reflect.person");
    } catch (Exception e) {
      e.printstacktrace ();
    }
    Get the parent class
    class<?> Temp=demo.getsuperclass ();
    System.out.println ("Inherited parent class is:  " +temp.getname ());
  }


"Run Results"

The inherited parent class is: Java.lang.Object

"Case": get all constructors in other classes

This example needs to add the import java.lang.reflect.* at the beginning of the program;

The main class is then written as:

Class hello{public
  static void Main (string[] args) {
    class<?> demo=null;
    try{
      demo=class.forname ("Reflect.person");
    } catch (Exception e) {
      e.printstacktrace ();
    }
    Constructor<?>cons[]=demo.getconstructors ();
    for (int i = 0; i < cons.length i++) {
      System.out.println ("constructor:" +cons[i]);}}

"Run Results":

Construction method: Public Reflect.person ()

Construction method: Public Reflect.person (java.lang.String)

But a careful reader will find that the constructor above does not have a modifier such as public or private.

Here's an example where we'll get the modifiers.

Class hello{public
  static void Main (string[] args) {
    class<?> demo=null;
    try{
      demo=class.forname ("Reflect.person");
    } catch (Exception e) {
      e.printstacktrace ();
    }
    Constructor<?>cons[]=demo.getconstructors ();
    for (int i = 0; i < cons.length i++) {
      class<?> p[]=cons[i].getparametertypes ();
      System.out.print ("Construction Method:");
      int mo=cons[i].getmodifiers ();
      System.out.print (modifier.tostring (MO) + "");
      System.out.print (Cons[i].getname ());
      System.out.print ("(");
      for (int j=0;j<p.length;++j) {
        System.out.print (p[j].getname () + "arg" +i);
        if (j<p.length-1) {
          System.out.print (",");
        }
      }
      System.out.println (") {}");}}

"Run Results":

Construct method: Public Reflect.person () {}

Construct method: Public Reflect.person (java.lang.String arg1) {}

Sometimes a method may have an exception, hehe. Look at the following:

Class hello{public static void Main (string[] args) {class&lt;?&gt; demo=null;
    try{demo=class.forname ("Reflect.person");
    }catch (Exception e) {e.printstacktrace ();
    Method Method[]=demo.getmethods ();
      for (int i=0;i&lt;method.length;++i) {class&lt;?&gt; returntype=method[i].getreturntype ();
      Class&lt;?&gt; para[]=method[i].getparametertypes ();
      int temp=method[i].getmodifiers ();
      System.out.print (modifier.tostring (temp) + "");
      System.out.print (Returntype.getname () + "");
      System.out.print (Method[i].getname () + "");
      System.out.print ("(");
        for (int j=0;j&lt;para.length;++j) {System.out.print (Para[j].getname () + "" + "arg" +j);
        if (j&lt;para.length-1) {System.out.print (",");
      } class&lt;?&gt; exce[]=method[i].getexceptiontypes ();
        if (exce.length&gt;0) {System.out.print (") throws"); for (int k=0;k&lt;exce.length;++k) {System.out.print (excE[k].getname () + "");
          if (k&lt;exce.length-1) {System.out.print (",");
      }}else{System.out.print (")");
    } System.out.println ();
 }
  }
}

"Run Results":

Public java.lang.String Getsex ()

public void Setsex (java.lang.String arg0)

public void Saychina ()

public void SayHello (java.lang.String arg0,int arg1)

Public final native void wait (long arg0) throws Java.lang.InterruptedException

Public final void Wait () throws Java.lang.InterruptedException

Public final void Wait (long arg0,int arg1) throws Java.lang.InterruptedException

public boolean equals (Java.lang.Object arg0)

Public java.lang.String toString ()

public native int Hashcode ()

Public final native Java.lang.Class GetClass ()

Public final native void Notify ()

Public final native void Notifyall ()

Case next let's get all the properties of the other classes, and finally I'll say these things together, which is to get all the frames of a class through class

Class Hello {public static void main (string[] args) {class&lt;?&gt; demo = null;
    try {demo = Class.forName ("Reflect.person");
    catch (Exception e) {e.printstacktrace ();
    } System.out.println ("=============== This class attribute ========================");
    Get all the properties of this class field[] Field = Demo.getdeclaredfields ();
      for (int i = 0; i &lt; field.length i++) {//rights modifier int mo = Field[i].getmodifiers ();
      String priv = modifier.tostring (MO);
      Property type Class&lt;?&gt; type = Field[i].gettype ();
    System.out.println (Priv + "" + type.getname () + "" + field[i].getname () + ";");}
    SYSTEM.OUT.PRINTLN ("=============== implemented interface or attribute ======================== of the parent class");
    Gets the implemented interface or the parent class's properties field[] filed1 = Demo.getfields ();
      for (int j = 0; J &lt; Filed1.length; J +) {//permission modifier int mo = Filed1[j].getmodifiers ();
      String priv = modifier.tostring (MO); Property type Class&lt;?&gt; type = Filed1[j].gettype();
 System.out.println (Priv + "" + type.getname () + "" + filed1[j].getname () + ";");}}

"Run Results":

=============== This class property ========================

Private java.lang.String sex;

=============== implements the interface or the properties of the parent class ========================

public static final java.lang.String name;

public static final int age;

A case can actually invoke a method in another class by reflection:

Class Hello {public
  static void Main (string[] args) {
    class<?> demo = null;
    try {
      demo = Class.forName ("Reflect.person");
    } catch (Exception e) {
      e.printstacktrace ();
    }
    try{
      //Invoke the Saychina method in the person class to
      Method=demo.getmethod ("Saychina");
      Method.invoke (Demo.newinstance ());
      Invoke the SayHello method of person
      method=demo.getmethod ("SayHello", string.class,int.class);
      Method.invoke (Demo.newinstance (), "Rollen");
       
    } catch (Exception e) {
      e.printstacktrace ();}}}

"Run Results":

Hello,

Rollen 20

"Case" calls the set and get methods of other classes

Class Hello {public static void main (string[] args) {class&lt;?&gt; demo = null;
    Object Obj=null;
    try {demo = Class.forName ("Reflect.person");
    catch (Exception e) {e.printstacktrace ();
    } try{obj=demo.newinstance ();
    }catch (Exception e) {e.printstacktrace ();
    Setter (obj, "Sex", "male", string.class);
  Getter (obj, "Sex"); /** * @param obj * Operation object * @param att * * */public static void Getter (Object obj,
      String att) {try {method method = Obj.getclass (). GetMethod (' get ' + att);
    System.out.println (Method.invoke (obj));
    catch (Exception e) {e.printstacktrace ();  /** * @param obj * Operation object * @param att * Operation properties * @param value * @param  Attribute */public static void Setter (Object obj, String att, object value, class&lt;?&gt; type) of type * parameter {try {Method method = Obj.getclass ().Method ("Set" + ATT, type);
    Method.invoke (obj, value);
    catch (Exception e) {e.printstacktrace ();

 }}//End Class

"Run Results":

Man

"Case" Action properties by reflection

Class Hello {public
  static void Main (string[] args) throws Exception {
    class<?> demo = null;
    Object obj = null;
 
    Demo = Class.forName ("Reflect.person");
    obj = Demo.newinstance ();
 
    Field field = Demo.getdeclaredfield ("Sex");
    Field.setaccessible (true);
    Field.set (obj, "male");
    System.out.println (Field.get (obj));
  }
End Class


The case gets and modifies the information of the array by reflection:

Import java.lang.reflect.*;
Class hello{public
  static void Main (string[] args) {
    int[] temp={1,2,3,4,5};
    Class<?>demo=temp.getclass (). Getcomponenttype ();
    SYSTEM.OUT.PRINTLN ("Array type:" +demo.getname ());
    SYSTEM.OUT.PRINTLN ("Array Length" +array.getlength (temp));
    System.out.println ("The first element of the array:" +array.get (temp, 0));
    Array.set (temp, 0, MB);
    SYSTEM.OUT.PRINTLN (the first element of the array after modification is: +array.get (temp, 0));
  }


"Run Results":

Array type: INT

Array length 5

The first element of the array: 1

After modification the first element of the array is: 100

"Case" modifies the size of an array by reflection

Class hello{public
  static void Main (string[] args) {
    int[] temp={1,2,3,4,5,6,7,8,9};
    Int[] newtemp= (int[]) arrayinc (temp,15);
    Print (newtemp);
    System.out.println ("=====================");
    String[] atr={"A", "B", "C"};
    String[] str1= (string[]) arrayinc (atr,8);
    Print (STR1);
  }
   
  /**
   * Modify array size
   *
  /public static object Arrayinc (Object Obj,int len) {
    class<?>arr= Obj.getclass (). Getcomponenttype ();
    Object newarr=array.newinstance (arr, Len);
    int co=array.getlength (obj);
    System.arraycopy (obj, 0, NEWARR, 0, CO);
    return NEWARR;
  }
  /** * */public
  static void print (Object obj) {
    class<?>c=obj.getclass ();
    if (!c.isarray ()) {return
      ;
    }
    SYSTEM.OUT.PRINTLN ("Array length is:" +array.getlength (obj));
    for (int i = 0; i < array.getlength (obj); i++) {
      System.out.print (array.get (obj, i) + "");}}


"Run Results":

The length of the array is: 15

1 2 3 4 5 6 7 8 9 0 0 0 0 0-0 =====================

The length of the array is: 8

A b c null null NULL

Dynamic Proxy

The case first looks at how to get the ClassLoader:

Class test{
   
}
class hello{public
  static void Main (string[] args) {
    Test t=new test ();
    SYSTEM.OUT.PRINTLN (class loader +t.getclass (). getClassLoader (). GetClass (). GetName ());
  }


"Program Output":

Class Loader Sun.misc.launcher$appclassloader

In fact, there are three kinds of class loaders in Java.

1) Bootstrap ClassLoader This loader is written in C + +, common development is very rare.

2) Extension ClassLoader is used to load extended classes, typically corresponding to classes in the Jre\lib\ext directory

3) Appclassloader load Classpath specified class, is the most commonly used loader. It is also the default loader in Java.

If you want to complete a dynamic proxy, you first need to define a subclass of the Invocationhandler interface, which completes the agent's actions.

 package reflect; import java.lang.reflect.*;
 
Defines the project interface interface Subject {public string say (string name, int age);  Define real Project class Realsubject implements Subject {@Override public string say (string name, int age) {return name +
  "+ Age;"
 
  Class Myinvocationhandler implements Invocationhandler {private Object obj = null;
    public object bind (Object obj) {this.obj = obj;
  Return Proxy.newproxyinstance (Obj.getclass (). getClassLoader (), obj. GetClass (). Getinterfaces (), this); @Override public Object Invoke (object proxy, Method method, object[] args) throws Throwable {object tem
    p = Method.invoke (this.obj, args);
  return temp;
    Class Hello {public static void main (string[] args) {Myinvocationhandler demo = new Myinvocationhandler ();
    Subject sub = (Subject) demo.bind (New Realsubject ());
    String info = Sub.say ("Rollen", 20);
  SYSTEM.OUT.PRINTLN (info); }
}

"Run Results":

Rollen 20

The life cycle of a class

After a class has been compiled, the next step is to start using the class, and if you want to use a class, you must not leave the JVM. In program execution the JVM completes the 3 steps by loading, linking, and initializing.

The loading of the class is done through the ClassLoader, which loads the binaries of the. class file into the method area of the JVM and creates a Java.lang.Class object that describes the class in the heap area. Used to encapsulate data. But the same class will only be loaded by the class loader before

A link is to assemble binary data into a state that can be run.

Links are divided into checksums, preparation, parsing these 3 stages

Checksums are generally used to confirm that this binary is appropriate for the current JVM (version).

Preparation is the allocation of memory space for static members. and set the default value

Parsing refers to the process of converting code in a constant pool as a direct reference until all symbolic references can be used by the running program (establish a complete correspondence)

When finished, the type is initialized, and the object of the class is used normally until an object is no longer in use and is garbage collected. Free space.

is unloaded when no reference is directed to the class object, ending the lifecycle of the class

Apply reflection to Factory mode

Let's take a look at the factory model if you don't have to reflect it:

Http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html

/**
 * @author rollen-holt design mode of the Factory mode * *
 
interface fruit{public
  abstract void Eat ();
 
Class Apple implements fruit{public
  void Eat () {
    System.out.println ("Apple");
  }
 
Class Orange implements fruit{public
  void Eat () {
    System.out.println ("Orange");
  }
 
Construct the factory class
//That is, if we need to modify the factory class only when we add other instances,
class factory{public
  static Fruit getinstance (String Fruitname) {
    fruit f=null;
    if ("Apple". Equals (Fruitname)) {
      f=new apple ();
    }
    if ("Orange". Equals (Fruitname)) {
      f=new orange ();
    }
    return f;
  }
}
Class hello{public
  static void Main (string[] a) {
    fruit f=factory.getinstance ("Orange");
    F.eat ();
  }
 

In this way, when we add a subclass, we need to modify the factory class. If we add too many subclasses, there will be a lot of changes.

Now let's take a look at the reflection mechanism:

package reflect;
 
Interface fruit{public
  abstract void Eat ();
}
 
Class Apple implements fruit{public
  void Eat () {
    System.out.println ("Apple");
  }
 
Class Orange implements fruit{public
  void Eat () {
    System.out.println ("Orange");
  }
 
Class factory{public
  static Fruit getinstance (String ClassName) {
    fruit f=null;
    try{
      f= (fruit) class.forname (ClassName). newinstance ();
    catch (Exception e) {
      e.printstacktrace ();
    }
    return f;
  }
}
Class hello{public
  static void Main (string[] a) {
    fruit f=factory.getinstance ("reflect.apple");
    if (f!=null) {
      f.eat ();}}}

Now even if we add as many subclasses as we want, the factory class doesn't need to be modified.

The love above? Although you can get an instance of an interface through reflection, you need to pass in the full package and class name. And the user has no way of knowing how many subclasses a single interface can use, so we configure the required subclasses in the form of a property file.

Let's take a look at: The factory model combining attribute files

First, create a fruit.properties resource file,

Content is:

Apple=reflect.apple
Orange=reflect.orange

Then write the main class code:

package reflect;
Import java.io.*;
 
Import java.util.*;
 
Interface fruit{public abstract void Eat ();}
  Class Apple implements fruit{public void Eat () {System.out.println ("Apple");
  Class Orange implements fruit{public void Eat () {System.out.println ("Orange"); }//Operations Properties File class class init{public static Properties Getpro () throws FileNotFoundException, ioexception{properties
    Pro=new Properties ();
    File F=new file ("Fruit.properties");
    if (f.exists ()) {Pro.load (new FileInputStream (f));
      }else{pro.setproperty ("Apple", "reflect.apple");
      Pro.setproperty ("Orange", "Reflect.orange");
    Pro.store (new FileOutputStream (f), "FRUIT CLASS");
  return pro;
    Class factory{public static Fruit getinstance (String ClassName) {fruit f=null;
    try{f= (Fruit) class.forname (ClassName). newinstance ();
    }catch (Exception e) {e.printstacktrace ();
  } return F; } class hello{public static void MaIn (string[] a) throws FileNotFoundException, ioexception{Properties Pro=init.getpro ();
    Fruit f=factory.getinstance (Pro.getproperty ("Apple"));
    if (f!=null) {f.eat ();

 }
  }
}

"Run Results": Apple

The above is the Java reflection mechanism of the detailed, follow-up to continue to supplement the relevant information, thank you for your support of this site!

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.