[Java]-depth analysis of Java reflection (1) - Basic

Article title: Insights Java reflection (1) - Basic
author of the article: sczyh30
original link: http://www.sczyh30.com/posts/Java/java-reflection-1/
license: reproduced please retain the original link and author

* This paper is a basic article, based on JDK 1.8.

I. Review: What is reflection?

Reflection (the Reflection) is one of the features of Java, it allows Java programs to run in its own information acquired, and may operate internal attributes of the class or object.

Oracle official explanation for reflection:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

In short, by reflection, we can get information about the program or assembly members and members of every type at run time. Program in general type of object are determined at compile down, and Java reflection to dynamically create an object and call its properties, this type of object is not known at compile time. So we can create an object by direct reflection mechanism, even if the type of the object is not known at compile time.

The core is reflected JVM dynamically loaded at runtime class or call methods / access properties, it requires no prior (write the code or compile) know who run the object yes.

Java reflection provides the following functions:

  • Determining at runtime object belongs to any class;
  • At runtime class of an object in any configuration;
  • Analyzing any class has member variables and methods (or even by the reflection method can be called private) at runtime;
  • Call any of the object's method at run time

Important: When is the runtime rather than compile

Second, the main purpose of the reflective

Many people think that is not widely reflected in the actual development of Java applications, it is not. When we use the IDE (such as Eclipse, IDEA), when we enter an object or class and want to call it a property or method, according to a number of points, the compiler will automatically listed in its property or method, here It will use reflection.
Reflecting the most important use is the development of a variety of common framework.
Many frameworks (such as Spring) is the configuration of (such as through XML configuration file Bean), in order to ensure universal framework, they may need to load a different object or class based on the profile, calling different methods, we must use this time the reflection object needs to be loaded dynamically loaded at runtime.

As an example, in the use of Struts 2 framework of development we generally configured in Action struts.xml go, such as:

<action name="login"
        class="org.ScZyhSoft.test.action.SimpleLoginAction"
        method="execute">
    <result>/shop/shop-index.jsp</result>
    <result name="error">login.jsp</result>
</action>

Profiles and Action establishes a mapping relationship, when the View layer makes a request, the request will be blocked StrutsPrepareAndExecuteFilter, then StrutsPrepareAndExecuteFilter will go to Action instance is created dynamically. For example, we request login.action, then StrutsPrepareAndExecuteFilter will go to resolve struts.xml file retrieval action for the login name in the Action, and create a class based on property SimpleLoginAction instance, and invoke a method to invoke the execute method, this process can not do without reflection.

And the framework for developers, reflecting a small but very large role, it is the core of a variety of containers implemented. For general developers, not in-depth development of the framework with little reflection will be a little, but look at the underlying institutional framework helps to enrich their programming ideas, is very useful.

Third, the basic use of reflection

We mentioned above may be used for the reflection of any object belongs Analyzing class, Class object is obtained, and an object construct arbitrary call an object. Here we introduce the use and implementation of basic reflex functions (related classes are generally reflected in java.lang.relfect bag).

1, the Class object

There are three ways:

  1. ForName use static methods of class Class:
public static Class<?> forName(String className)
/**
 *	比如在 JDBC 开发中常用此方法加载数据库驱动:
 *	Class.forName(driver);
 **/
  1. Direct access to a certain class of objects, such as:
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;
  1. Call an object getClass () method, for example:
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();

2, it is determined whether an instance of a class

In general, we use the instanceof keyword to determine whether an instance of a class. We can also reflected by objects in Class isInstance () method to determine whether an instance of a class, which is a native methods:

public native boolean isInstance(Object obj);

3, create an instance

It is generated by reflecting object mainly in two ways.

  1. Class objects using newInstance () method creates an instance of the corresponding class Class object.
Class<?> c = String.class;
Object str = c.newInstance();
  1. First obtain the specified Class Constructor object by object, calls the Constructor object newInstance () method to create an instance. This method can be configured with the specified instance of the class constructor.
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);

4, acquisition method

Class object to obtain a set of methods, mainly in the following methods:

  1. All methods getDeclaredMethods method returns the class or interface declaration, including the public, protected, default (package) access, and private methods, but excludes inherited methods.
public Method[] getDeclaredMethods() throws SecurityException
  1. getMethods method returns all public (public) method of a class, including its public methods inherited class.
public Method[] getMethods() throws SecurityException
  1. getMethod method returns a particular method, wherein the first parameter is the name of the method, the latter parameter is an object corresponding to the parameters of the method of the Class.
public Method getMethod(String name, Class<?>... parameterTypes)

Just so described, then it may be difficult to understand, we use the example to understand these three methods:

package org.ScZyhSoft.common;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class test1 {
	public static void test() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
	        Class<?> c = methodClass.class;
	        Object object = c.newInstance();
	        Method[] methods = c.getMethods();
	        Method[] declaredMethods = c.getDeclaredMethods();
	        //获取methodClass类的add方法
	        Method method = c.getMethod("add", int.class, int.class);
	        //getMethods()方法获取的所有方法
	        System.out.println("getMethods获取的方法:");
	        for(Method m:methods)
	            System.out.println(m);
	        //getDeclaredMethods()方法获取的所有方法
	        System.out.println("getDeclaredMethods获取的方法:");
	        for(Method m:declaredMethods)
	            System.out.println(m);
	    }
    }
class methodClass {
    public final int fuck = 3;
    public int add(int a,int b) {
        return a+b;
    }
    public int sub(int a,int b) {
        return a+b;
    }
}

Results of the program run as follows:

getMethods获取的方法:
public int org.ScZyhSoft.common.methodClass.add(int,int)
public int org.ScZyhSoft.common.methodClass.sub(int,int)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
getDeclaredMethods获取的方法:
public int org.ScZyhSoft.common.methodClass.add(int,int)
public int org.ScZyhSoft.common.methodClass.sub(int,int)

It can be seen, the method can be acquired by the acquisition getMethods () method of the parent class, such as the various methods defined java.lang.Object.

5, configured to obtain information

Get Class constructor method for acquiring usage and usage similar to the above. And is obtained by an instance of class Constructor getConstructor method Class class, and a class Constructor newInstance method can create an object instance:

public T newInstance(Object ... initargs)

This method can be invoked in accordance with the corresponding parameters passed Constructor to create an object instance.

6, member variables to get a class of (field) information

Mainly these methods are not repeated here:

  • getFiled: access to public member variables
  • getDeclaredField: all member variables have been declared, but can not be a member variable of the parent class

getFileds getDeclaredFields methods and uses as above (see Method).

7, call the method

When we get a way from the class, we will invoke () method to call this method. Prototype invoke method is:

public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException

Here is an example:

public class test1 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> klass = methodClass.class;
        //创建methodClass的实例
        Object obj = klass.newInstance();
        //获取methodClass类的add方法
        Method method = klass.getMethod("add",int.class,int.class);
        //调用method对应的方法 => add(1,4)
        Object result = method.invoke(obj,1,4);
        System.out.println(result);
    }
}
class methodClass {
    public final int fuck = 3;
    public int add(int a,int b) {
        return a+b;
    }
    public int sub(int a,int b) {
        return a+b;
    }
}

Detailed invoke methods on the back I will write an article dedicated to in-depth analysis invoke the process. Click here to jump

8, using the reflection to create an array

Array is a special type in Java, it can be assigned to an Object Reference. Let's look at an example using the reflection to create an array:

public static void testArray() throws ClassNotFoundException {
        Class<?> cls = Class.forName("java.lang.String");
        Object array = Array.newInstance(cls,25);
        //往数组里添加内容
        Array.set(array,0,"hello");
        Array.set(array,1,"Java");
        Array.set(array,2,"fuck");
        Array.set(array,3,"Scala");
        Array.set(array,4,"Clojure");
        //获取某一项的内容
        System.out.println(Array.get(array,3));
    }

Wherein java.lang.reflect.Array Array class category. We () to create an array of objects through Array.newInstance, its prototype is:

public static Object newInstance(Class<?> componentType, int length)
        throws NegativeArraySizeException {
        return newArray(componentType, length);
    }

The newArray method is a native method, which in particular in the HotSpot JVM implementation is behind us and then study the source code posted here first:

private static native Object newArray(Class<?> componentType, int length)
        throws NegativeArraySizeException;

Source directory: openjdk \ hotspot \ src \ share \ vm \ runtime \ reflection.cpp

arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) {
  if (element_mirror == NULL) {
    THROW_0(vmSymbols::java_lang_NullPointerException());
  }
  if (length < 0) {
    THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
  }
  if (java_lang_Class::is_primitive(element_mirror)) {
    Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
    return TypeArrayKlass::cast(tak)->allocate(length, THREAD);
  } else {
    Klass* k = java_lang_Class::as_Klass(element_mirror);
    if (k->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
      THROW_0(vmSymbols::java_lang_IllegalArgumentException());
    }
    return oopFactory::new_objArray(k, length, THREAD);
  }

Further, Array class set and get methods are native methods, where the HotSpot JVM correspond Reflection :: array_set Reflection :: array_get and methods, not described in detail here resolved.

Fourth, the reflection of some of the considerations

Since the reflection extra consume some system resources, so if you do not need to dynamically create an object, you do not need reflection.

In addition, you can ignore when checking permissions reflection to invoke methods, so could undermine the encapsulation and lead to security problems.

Guess you like

Origin blog.csdn.net/shaotaiban1097/article/details/91947788