table of Contents
First, reflection
1 Overview
Reflection: the various components of the package into the category of other objects in the operating state, can be dynamically obtain class information and call the class object's method.
2, advantages and disadvantages
- advantage
- It may be the program is running, the operation part of the class.
- Decoupling can improve the scalability of the program.
- Shortcoming
- Produce a series of operations explained, poor performance.
3, the class loading procedure
java language has "a compilation, run anywhere" characteristics of the fine, able to adapt to different platforms, the process is as follows:
- We
javac
command.java
file is compiled, it will generate on the disk platform that does not face the bytecode files.class
. - After the class loader through a series of operations, such as loading, and the connection initialization, the
.class
file is loaded into memory. - Static storage structure .class file represents bytecode runtime data structures into the method area.
- Then the class loader will be created when a memory
java.lang.Class
object, the object contains information such as access data from a variety of areas as a method of programming interface.
Second, get the Class object of three ways
The Class object contains all the information category, that is, we get the Class object class, you can access the JVM in this class. So, how to get it? There are three main ways.
1、Class.forName("全类名")
By Class的静态方法forName("全类名")
, Class object and returns the corresponding full class name of the class.
//Class.forName("全类名");
Class cls1 = Class.forName("com.my.base.Person");
System.out.println(cls1);
- Used for the configuration file, the class name is defined in the configuration file, you can read files dynamically load classes.
- Full class name refers to: the full package name class name, if found, will throw ClassNotFoundException exception.
2, the class name .class
By 类名的class属性
obtaining, returns the object corresponding to the class Class.
//类名.class;
Class cls2 = Person.class;
System.out.println(cls2);
- The way the program is compiled stage to check whether there is a need to access the Class object, relatively more secure.
- The way without having to call a method, program performance is relatively good.
3, the object .getClass ()
getClass()
The method defined in Object, which returns the object's class to obtain the corresponding Class object.
//对象.getClass();
Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3);
The same byte code file .class
in the course of a program is running, it will only be loaded once, regardless of which way acquired by Class objects are the same.
// == 比较三个对象,都是true
System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);
System.out.println(cls3 == cls2);
Third, the reflection correlation method
Class object contains information of all classes, which are encapsulated within java.lang.reflect
the package, has become one of the class, incomplete follows:
Method | Field | Annotation | Constructor | Package | Modifier | Parameter |
---|---|---|---|---|---|---|
Method in class | Field class | Class Notes | The class constructor | Bags | Modifiers class | Method parameter class |
Class in the appropriate class provides methods to obtain this information, due to the numerous methods, specific JDK also need to see official documents.
Here I summarize a few general:
Call the corresponding
getXxx
usually obtain public information corresponding to a single modification,getDeclaredXxx
is not considered modifiers, can not be found, the superclass to find.Call the corresponding
getXxxs
usually get an array of public information corresponding modification,getDeclaredXxxs
modifier is not considered, can not be found, the superclass to find.- The above parameters encountered two different situations, if the method itself is used to obtain public information modified forced to get permission to fail, it will throw an exception:
- For Field, the brackets are:
"参数名"
. - For Method, in parentheses:
"方法名",参数类型对应的类
. - For Constructor, in parentheses:
"参数对应的类"
.
- For Field, the brackets are:
- Field class has a method to get the value of:
Object get(Object obj)
, there is provided a method values:void set(Object obj, Object value)
. - Method class can invoke methods:
Object invoke(Object obj, Object... args)
. Constructor class creates instances:
T newInstance(Object... initargs)
if no-argument constructor class, can be used directly in class Class newInstance () method creates an instance.- In reflection, nothing is private, if there is, then the use of
xxx.setAccessible(true)
brute force. Modifier is determined,
getModifiers()
when the value of the return int is the modifier indicating the number of the individual and can be determined by bit operation,(xx.getModifiers()&Modifier.STATIC)!=0
indicating the presence of the static modifier.
ps: there must be missing API, to use the time when, looking through the API gets the job done.
Four, Demo × 2
1, try to write a clone () method
package com.my.reflect.practice;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* @auther Summerday
*/
@SuppressWarnings("unchecked")
public class ImplementClone {
public Object clone(Object o) throws Exception{
//获取对象的实际类型
Class<Object> clz = (Class<Object>) o.getClass();
//获取所有构造方法
Constructor<Object>[] cs = (Constructor<Object>[]) clz.getDeclaredConstructors();
//任取一个构造方法
Constructor<Object> c = cs[0];
//防止取出构造方法为私有
c.setAccessible(true);
//该构造方法参数有or无?
//获取参数类型
Class[] ps = c.getParameterTypes();
//存储参数的数组
Object[] os = new Object[ps.length];
for(int i = 0;i<ps.length;i++){
//判断是否为基本类型
if(ps[i].isPrimitive()){
if(ps[i] == boolean.class)
os[i] = false;
else if(ps[i] == char.class)
os[i] = '\u0000';
else
os[i] = 0;
}else{
os[i] = null;
}
}
//执行构造方法创建对象
Object obj = c.newInstance(os);
//获取属性数组
Field[] fs = clz.getDeclaredFields();
for (Field f : fs){
//如果final修饰则返回,无法修改
if((f.getModifiers()&Modifier.FINAL)!=0){
continue;
}
//暴力破解
f.setAccessible(true);
//取出原属性值
Object value = f.get(o);
//将取出的属性值赋值给新对象的属性
f.set(obj, value);
}
return obj;
}
}
2, using the configuration file dynamic loading
package com.my.reflect.practice;
/**
* @auther Summerday
*/
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
/**
*
* 参考黑马程序员教学视频
*
* 实现:1、配置文件 2、反射
*
* 一、将需要创建的对象的全类名和需要执行的方法定义在配置文件中
*
* 二、在程序中加载读取配置文件
*
* 三、使用反射来加载类文件进内存
*
* 四、创建对象
*
* 五、执行方法
*
*/
public class ReflectTest {
public static void main(String[] args) throws Exception {
//1、加载配置文件
//1.1 创建Properties对象
Properties pro = new Properties();
//1.2 加载配置文件,转换为一个集合
//1.2.1获取class目录下的配置文件
//创建类加载器
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
pro.load(resourceAsStream);
//2、获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3、加载该类进内存
Class cls = Class.forName(className);
//4、创建对象
Object obj = cls.newInstance();
//5、获取方法
Method method = cls.getMethod(methodName);
//6、执行方法
method.invoke(obj);
}
}
It will have more and more need to use real scenarios reflecting the soul of technology, in short, a good look, a good school.