在理解动态代理之前,需要理解一下反射的概念和基础。
一、定义
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。可以理解为在运行时期获取对象类型信息的操作。传统的编程方法要求程序员在编译阶段决定使用的类型,但是在反射的帮助下,编程人员可以动态获取这些信息,从而编写更加具有可移植性的代码。
二、Class类
Class这个类用于操纵一个类的属性,方法,构造器。众所周知Java有个Object类,是所有Java类的继承根源,其内声明了数个应该在所有Java类中被改写的方法,hashCode(), equals(), clone(), toString(), getClass()等。其中getClass()返回一个Class对象。Class类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive java types(boolean, byte, char, int, long, float, double) 以及关键词void。当一个class类被加载,或者当加载器(class loader)的defineClass() 被JVM调用,JVM便自动产生一个Class类对象。
三、获取Class对象的三种方式
1)Class.forName("classpath"):classpath为类所在的路径。
2)object.class
3)object.getClass()
举个例子:
首先定义一个Person类:
package com.csdn.reflect;
public class Person {
private String name;
private String address;
private int age;
public Person() {
}
public Person(String name, String address, int age) {
this.name = name;
this.address = address;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", age=" + age +
'}';
}
}
ReflectDemo:
package com.csdn.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Person p = new Person();
testForName();
testDotClass();
testGetClass(p);
}
public static void testForName() throws Exception{
System.out.println("=========testForName start===============");
//也能获得一个类的类对象
Class> clazz = Class.forName("com.csdn.reflect.Person");
output(clazz);
System.out.println("=========testForName end===============");
}
public static void testGetClass(Object obj) {
System.out.println("=========testGetClass start===============");
//也能获得一个类的类对象
Class> clazz = obj.getClass();
output(clazz);
System.out.println("=========testGetClass end===============");
}
public static void testDotClass() {
System.out.println("=========testDotClass start===============");
//也能获得一个类的类对象
Class> clazz = Person.class;
output(clazz);
System.out.println("=========testDotClass end===============");
}
public static void output(Class clazz) {
//获得传递过来的类的所有方法
Method[] methods = clazz.getDeclaredMethods();
for(Method m : methods) {
System.out.println(m);
}
System.out.println("-----------------------------------------");
//获得类的所有属性
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("-----------------------------------------");
//获得类的所有的构造器
Constructor>[] cs = clazz.getDeclaredConstructors();
for(Constructor c: cs) {
System.out.println(c);
}
}
}
四、反射举例
可以通过类对象来获取属性Field,方法Method,以及构造器Constructor,通过构造器可以用来生成新的对象,并通过反射调用来调用类方法。举个栗子:
ReflectDemo1:
package com.csdn.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectDemo1 {
public static void main(String[] args) throws Exception {
Class> clazz = Class.forName("com.csdn.reflect.Person");
//获得类对象的一个属性
Field field = clazz.getDeclaredField("address");
System.out.println(field);
//获得一个具体的方法
Method method = clazz.getDeclaredMethod("getName", new Class[]{});
System.out.println(method);
Method method1 = clazz.getDeclaredMethod("setName", new Class[]{String.class});
System.out.println(method1);
//获得构造器
Constructor> constructor = clazz.getDeclaredConstructor(new Class[]{});
System.out.println(constructor);
//根据类的默认构造器来获得一个对象
Object instance = constructor.newInstance(new Object[]{});
//get setName method
Method mSet = clazz.getDeclaredMethod("setName", new Class[]{String.class});
//call method on the instance object
Object invoke = mSet.invoke(instance, new Object[]{"lebaishi"});
System.out.println(invoke);
//get getName method
Method mGet = clazz.getDeclaredMethod("getName", new Class[]{});
//call method on the install object
Object invoke2 = mGet.invoke(instance, new Object[]{});
System.out.println(invoke2);
}
}
Author:忆之独秀
Email:[email protected]
注明出处:https://blog.csdn.net/lavorange/article/details/86190050