The class reflection mechanism in Java

Source: Internet
Author: User
Tags define array command line extend header implement integer tostring
First, the concept of reflection:
The concept of reflection was first proposed by Smith in 1982, mainly referring to the ability of a program to access, detect, and modify its own state or behavior. The idea of this concept soon triggered a study of the application of reflection in the field of computer science. It was first adopted in the field of programming language design, and achieved results in Lisp and object-oriented aspects. Among them, lead/lead++, openc++, Metaxa and Openjava are language based on reflection mechanism. Recently, the reflection mechanism has also been applied to Windows, operating systems, and file systems.

Reflection is not a new concept in itself, it may remind us of the concept of reflection in optics, although computer science gives a new meaning to the concept of reflection, but there are certain similarities in the phenomena that help us understand. In the field of computer science, reflection refers to a class of applications that can be self-describing and self controlled. In other words, such applications use a mechanism to implement descriptions of their actions (self-representation) and monitoring (examination), and to adjust or modify the state and associated semantics of the behavior described by the application according to the State and the outcome of its behavior. It can be seen that, compared with the general concept of reflection, reflection in the field of computer science does not merely mean the reflection itself, but also the measures taken to reflect the results. All systems with reflective mechanisms (i.e., reflection systems) want to make the system more open. It can be said that the system which realizes the reflection mechanism has the openness, but the open system does not necessarily adopt the reflection mechanism, the openness is the necessary condition of the reflective system. In general, the reflective system must satisfy the causal connection (causally-connected) In addition to satisfying the open conditions. The so-called causal connection refers to the reflection system self-describing changes can immediately reflect the actual state and behavior of the system at the bottom of the situation, and vice versa. Open and causal connections are two basic elements of a reflective system. 13700863760

In Java, Reflection is a powerful tool. It enables you to create flexible code that can be assembled at run time without the need for source-representative links between components. Reflection allows us to enable our program code to access the internal information of classes loaded into the JVM, rather than the code of the classes that are selected in the source code, when writing and executing. This makes reflection a major tool for building flexible applications. However, it is important to note that if used improperly, the cost of reflection is high.

Second, class reflection in Java:
Reflection is one of the characteristics of Java Program Development language, it allows the running Java program to check itself, or "self audit", and can directly manipulate the internal properties of the program. This capability of Java may not be used in many practical applications, but it does not exist in other programming languages at all. For example, there is no way in Pascal, C, or C + + to get information about function definitions in a program.

1. Test class:

The working mechanism of 1.1 reflection

Consider the following simple example, let's see how reflection works.

Import java.lang.reflect.*;
public class Dumpmethods {
public static void Main (String args[]) {
try {
Class C = class.forname (Args[0]);
Method m[] = C.getdeclaredmethods ();
for (int i = 0; i < m.length; i++)
System.out.println (M[i].tostring ());
catch (Throwable e) {
System.err.println (e);
}
}
}

Follow the following statement:

Java dumpmethods Java.util.Stack

Its result output is:

Public Java.lang.Object Java.util.Stack.push (java.lang.Object)

Public synchronized Java.lang.Object Java.util.Stack.pop ()

Public synchronized Java.lang.Object Java.util.Stack.peek ()

public boolean java.util.Stack.empty ()

public synchronized int Java.util.Stack.search (java.lang.Object)

This lists the method names of the Java.util.Stack class and their qualifiers and return types.

This program uses Class.forName to load the specified class and then calls Getdeclaredmethods to get a list of the methods defined in the class. Java.lang.reflect.Methods is a class used to describe a single method in a class.

The main methods in 1.2 Java class reflection

For any of the following three types of components-constructors, fields, and methods-Java.lang.Class provides four separate reflection invocations to obtain information in different ways. Calls follow a standard format. The following is a set of reflection calls to find constructors:

L Constructor GetConstructor (class[] params)--Gets a public constructor that uses a particular parameter type.

L constructor[] GetConstructors ()--get all public constructors for a class

L Constructor Getdeclaredconstructor (class[] params)--get a constructor that uses a specific parameter type (regardless of the access level)

L constructor[] Getdeclaredconstructors ()--gets all constructors of the class (regardless of access level)

Class reflection calls to get field information are different from those used to access constructors, and field names are used in an array of parameter types:

L field GetField (String name)--Get a named public field

L field[] GetFields ()--Get all public fields of a class

L field Getdeclaredfield (String name)--Gets the named field declared by the class

L field[] Getdeclaredfields ()--Get all the fields declared by the class

To get the method information function:

L Method GetMethod (String name, class[] params)--use a specific parameter type to obtain a named public method

L method[] GetMethods ()--Get all the public methods of a class

L Method Getdeclaredmethod (String name, class[] params)--Methods for naming a class declaration using a feature parameter type

L method[] Getdeclaredmethods ()--all methods for obtaining a class declaration



1.3 Start using Reflection:

Classes used for reflection, such as method, can be found in the Java.lang.relfect package. There are three steps you must follow to use these classes: The first step is to get the Java.lang.Class object of the class you want to manipulate. In a running Java program, use the Java.lang.Class class to describe classes and interfaces.

Here's one way to get a Class object:

Class C = class.forname ("java.lang.String");

This statement gets the class object of a String class. There is another way, such as the following statement:

Class C = int.class;

Or

Class C = integer.type;

They can obtain class information of the basic type. The latter method accesses the predefined type fields in the encapsulated class (such as Integer) of the base types.

The second step is to call a method such as Getdeclaredmethods to get a list of all the methods defined in the class.

Once you get this information, you can take the third step--use the reflection API to manipulate this information, such as the following code:

Class C = class.forname ("java.lang.String");

Method m[] = C.getdeclaredmethods ();

System.out.println (M[0].tostring ());

It will print out the prototype of the first method defined in String in a textual way.

2. Working with objects:

If you want to make a development tool like debugger, you must be able to discover filed values, here are three steps:

A. Create a Class object
B. Creating a Field object from GetField
C. Call Field.getxxx (object) method (XXX is int,float, if object is omitted; object is an instance).

For example:
Import java.lang.reflect.*;
Import java.awt.*;

Class Sampleget {

public static void Main (string[] args) {
Rectangle r = new Rectangle (100, 325);
Printheight (R);

}

static void Printheight (Rectangle r) {
Field Heightfield;
Integer Heightvalue;
Class C = R.getclass ();
try {
Heightfield = C.getfield ("height");
Heightvalue = (Integer) heightfield.get (R);
System.out.println ("Height:" + heightvalue.tostring ());
catch (Nosuchfieldexception e) {
System.out.println (e);
catch (SecurityException e) {
System.out.println (e);
catch (Illegalaccessexception e) {
System.out.println (e);
}
}
}



Iii. Security and Reflection:
Security is a more complex issue when dealing with reflection. Reflection is often used by frame code, and because of this, we may want the framework to have full access to the code without considering the usual access restrictions. In other cases, however, uncontrolled access poses a serious security risk, such as when a contemporary code is running in an environment that is not trustworthy for code sharing.

Because of these conflicting requirements, the Java programming language defines a multi-level approach to handling the security of reflection. The basic pattern is the same restrictions on reflection implementation as applied to source code access:

n access from any position to a class of public components

n classes have no access to private components outside of themselves

N Limited access to protected and packaged (default access) components

At least sometimes, however, there is an easy way around these limits. We can extend a common basic class Java.lang.reflect.AccessibleObject class in the class that we write. This class defines a setaccessible method that enables us to start or turn off access detection for instances of one of these classes. The only problem is that if you use the Security Manager, it will detect if the code that is shutting down access detection is licensed to do so. If not licensed, the Security manager throws an exception.

The following is a program that uses reflection on an instance of the Twostring class to show that security is running:

public class Reflectsecurity {

public static void Main (string[] args) {

try {

twostring ts = new Twostring ("A", "B");

Field field = Clas.getdeclaredfield ("m_s1");

Field.setaccessible (TRUE);

SYSTEM.OUT.PRINTLN ("Retrieved value is" +

Field.get (inst));

catch (Exception ex) {

Ex.printstacktrace (System.out);

}

}

}

If we compile this program and run it directly from the command line without using any particular parameter, it throws a Illegalaccessexception exception in the field. Get (inst) call. If we do not annotate field.setaccessible (true) lines, recompile and rerun the code, it will compile successfully. Finally, if we add JVM parameter-djava.security.manager to the command line to implement the security manager, it will still fail to compile unless we define permission for the Reflectsecurity class.

Four, reflective performance:
Reflection is a powerful tool, but there are some deficiencies. One of the major drawbacks is the performance impact. Using reflection is basically an interpretation operation, we can tell the JVM what we want to do and it meets our requirements. Such operations are always slower than performing the same operations directly.

The following program is an example of field access performance testing, including basic test methods. Each method tests a form of field access--Accesssame cooperates with the member fields of the same object, Accessother uses the fields of another object that can be accessed directly, accessreflection using a field of another object that can be accessed through reflection. In each case, the method performs the same calculation-the simple Add/multiply order in the loop.

The procedure is as follows:

public int accesssame (int loops) {

m_value = 0;

for (int index = 0; index < loops; index++) {

M_value = (m_value + additive_value) *

Multiplier_value;

}

return m_value;

}



public int accessreference (int loops) {

Timingclass timing = new Timingclass ();

for (int index = 0; index < loops; index++) {

Timing.m_value = (Timing.m_value + additive_value) *

Multiplier_value;

}

return timing.m_value;

}



public int accessreflection (int loops) throws Exception {

Timingclass timing = new Timingclass ();

try {

Field field = Timingclass.class.

Getdeclaredfield ("M_value");

for (int index = 0; index < loops; index++) {

int value = (Field.getint (timing) +

Additive_value) * Multiplier_value;

Field.setint (timing, value);

}

return timing.m_value;

catch (Exception ex) {

System.out.println ("Error using reflection");

Throw ex;

}

}

In the example above, the test program repeatedly calls each method and uses a number of cycles to measure the result on an average of multiple times. The average does not include the time of the first invocation of each method, so initialization time is not a factor in the result. The following figure clearly shows us how long each method field is accessed:

Figure 1: Field access time:

We can see that in the first two graphs (Sun JVM), the execution time of using reflection is more than 1000 times times that of direct access. By comparison, the IBM JVM may be slightly better, but the reflection method still needs to be 700 times times longer than other methods. There is no significant difference in time between the other two methods on any JVM, but the IBM JVM is almost one times faster than the Sun JVM. Most likely, this discrepancy reflects the professional optimizations of the sun Hot Spot JVM, which has done poorly on simple benchmarks. Reflection performance is an area of concern when Sun develops the 1.4 JVM, which is displayed in the reflection method invocation results. In terms of the performance of such operations, the Sun 1.4.1 JVM shows a significant improvement over the 1.3.1 version.

If you write a similar timing test program for creating objects that use reflection, we find that the difference in this case is not as significant as the field and method invocation. Using newinstance () calls to create a simple java.lang.Object instance takes about 12 times times the use of new Object () on the Sun 1.3.1 JVM, four times times that of the IBM 1.4.0 JVM, but only sun 1.4.1 Two parts on the JVM. Creating an array using Array.newinstance (type, size) is twice times as much as using new type[size on any test JVM, and the difference is narrowing as the array size increases.

Conclusion:
Java language Reflection provides a versatile way to dynamically link program components. It allows programs to create and control objects of any class (based on security restrictions) without having to hard-code the target class in advance. These features make reflection particularly useful for creating libraries that collaborate with objects in a very common way. For example, reflection is often used in a framework that continuously stores objects as databases, XML, or other external formats. Java reflection is useful for enabling classes and data structures to dynamically retrieve relevant information by name and to allow manipulation of this information in running programs. This feature of Java is very powerful and is not available in other common languages, such as C, C + +, Fortran, or Pascal.

But reflection has two disadvantages. The first is a performance problem. Reflection is much slower than direct code for field and method access. The extent of the performance problem depends on how reflection is used in the program. Slow performance will not be a problem if it acts as a relatively small part of the program's operation. Even the worst-case timings in the test show a reflection operation that only consumes a few microseconds. Performance issues become critical only when reflection is used in the core logic of performance-critical applications.

A more serious disadvantage of many applications is that using reflection blurs what is actually going on inside the program. Program personnel want to see the logic of the program in the source code, such as reflection, bypassing the source code technology will bring maintenance problems. The reflection code is more complex than the corresponding direct code, as seen in the code instance for performance comparisons. The best solution to these problems is to use reflection conservatively--only where it can really add flexibility--to record its use in the target class.





Dynamic loading of classes using reflection




Bromon Original Please respect the copyright

Recently wrote a mobile value-added project in Chengdu, I am responsible for the backend server. function is very simple, mobile phone users through GPRS open socket and server connection, I based on the data sent by users to respond. Brothers who have done similar projects must know that first you need to define a communication protocol similar to MSNP, but today's topic is how to design a highly scalable system. Since the project itself has not conducted a more sophisticated customer communication and demand analysis, so there will certainly be a lot of functional expansion, communication protocol will be more and more large, and I as a less diligent person, of course, do not want to modify the written program, so this project is a good opportunity to practice object-oriented design.

First, define an interface to isolate the class:

Package org.bromon.reflect;

public interface Operator

{

Public Java.util.List Act (java.util.List params)

}

According to the principle of design pattern, we can write different classes for different functions, each class inherits the operator interface, and the client only needs to program the operator interface to avoid a lot of trouble. such as this class:

Package org.bromon.reflect.*;

public class Success implements Operator

{

Public Java.util.List Act (java.util.List params)

{

List result=new ArrayList ();

Result.add (New String ("successful Operation"));

return result;

}

}

We can also write many other classes, but there's a problem, the interface is not instantiated, we have to manually control which class is specifically instantiated, which is very uncomfortable, if you can pass an argument to the application, let yourself choose to instantiate a class, execute its act method, then our work is much easier.

Fortunately, I use Java, only Java to provide such a reflection mechanism, or introspection mechanism, can achieve our unreasonable requirements. Write a configuration file emp.properties:

#成功响应

1000=success

#向客户发送普通文本消息

2000=load

#客户向服务器发送普通文本消息

3000=store

The key name in the file is the message header that the customer will send to me. The customer sends 1000 to me, then I execute the Act method of success class, similar if Send 2000 to me, then execute the Act method of the Load class, so the system conforms to the open and closed principle completely, if want to add new function, There is no need to modify the existing code, just add the corresponding rule in the configuration file, then write the new class, implement the Act method OK, even if I abandon this project, it will be able to extend well in the future. Such a system has a very good extensibility and pluggable nature.

The following example shows the dynamic loading function, in which the program knows which class should be instantiated when it is executed:

Package org.bromon.reflect.*;

Import java.lang.reflect.*;

public class Testreflect

{

Load configuration file, query message header for class name

private string Loadprotocal (string header)

{

String Result=null;

Try

{

Properties Prop=new properties ();

FileInputStream fis=new FileInputStream ("emp.properties");

Prop.load (FIS);

Result=prop.getproperty (header);

Fis.close ();

}catch (Exception e)

{

System.out.println (e);

}

return result;

}

Respond to messages, import the corresponding classes with reflection

public string Response (string header,string content)

{

String Result=null;

String S=null;

Try

{

/*

* Import Property file emp.properties, query the name of the class that corresponds to the header

* Dynamically load matching classes through reflection mechanism, all classes are isolated by operator interfaces

* You can extend the protocol by modifying the property file, adding a new class (inheriting the Msgoperator interface)

*/

S= "Org.bromon.reflect." +this.loadprotocal (header);

Load class

Class C=class.forname (s);

To create a case for a class

Operator mo= (Operator) c.newinstance ();

Construct parameter list

Class Params[]=new class[1];

Params[0]=class.forname ("Java.util.List");

Query Act method

Method M=c.getmethod ("act", params);

Object Args[]=new object[1];

Args[0]=content;

Call the method and get the return

Object Returnobject=m.invoke (Mo,args);

}catch (Exception e)

{

System.out.println ("Handler-response:" +e);

}

return result;

}

public static void Main (String args[])

{

Testreflect tr=new testreflect ();

Tr.response (Args[0], "message content");

}

}

Test: Java testreflect 1000

This program is for operator programming, so no need to make any changes, directly provide the load and store class, you can support 2000, 3000 calls to make parameters.

With such an introspective mechanism, the function of the interface can be played to the extreme, the design pattern can also reflect the power, not only for us to chat after dinner.





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.