资料来源:https://blog.csdn.net/zhangchen124
A:概念:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;public、protected、private。(面向对象),private私有的,不能访问。这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
B:原理:要知道方式机制之前,需要知道类的加载。类在运行过程中,会被加载进jvm,jvm将java文件编译成.class文件。而反射就是基于.class文件来实现的。一个类在运行过程中,会生成对应的.class文件,通过对.class文件可以获取该类的成员变量,构造方法,成员方法。
这里需要类加载器的功能实现对class文件编辑,涉及到JVM的原理,这里就不涉及了(迷)。
C:反射机制的作用:可以获取类的全部成员变量,成员方法,构造方法;反射是java框架设计的灵魂,很多框架都是基于思想实现的的。
通过反射的概念,我们需要获取该类运行时期的Class对象通过该对象获取到字节码文件内容。java提供了三种获取方式。
A:Objext类提供的:类 getClass() :返回此 Object的运行时类。
B:Class类的静态方法:static 类 forName(String name, boolean initialize, ClassLoader loader) :使用给定的类加载器返回与给定字符串名称的类或接口相关联的 类对象。
C:数据类型的静态属性class属性。
通常使用的是Class类提供的方法,便于将类配置在配置文件中,例如:Class.forName(“com.tjb.Person”);
查看Class类的API,提供了通过反射获取某个类的成员变量(Field),构造方法(Constructor),成员方法(Method),枚举(EnumConstant)的相关类
1,获取成员变量
A:获取公共成员变量
Field getField(String name) :返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 类对象。
Field[] getFields() :返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 类对象。
B:获取全部的成员变量 或单个非公共成员变量
Field getDeclaredField(String name) :返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 类对象。
Field[] getDeclaredFields() :返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。
注意:如果是获取非公共资源,在获取之前,需要通过设置获取权限AccessibleObject类为成员变量,构造方法,成员方法,枚举提供了反射获取访问权限。
void setAccessible(boolean flag) :将此对象的 accessible标志设置为指示的布尔值。
C:获取该类的Field对象
T newInstance(String name) :创建由此 类对象表示的类的新实例。
D:设置
public void set(Object obj,Object value):将给Filed示例的属性设置成value
代码示例:
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class c = Class.forName("cn.itcast_01.Person");
Constructor con = c.getConstructor();
Object obj = con.newInstance();
System.out.println(obj);
Field addressField = c.getField("address");
addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
System.out.println(obj);
}
}
2,获取构造方法实例
A:获取公共构造方法
public Constructor getConstructor(Class... parameterTypes):获取单个公共构造方法
public Constructor[] getConstructors():所有公共构造方法
B:获取全部的构造方法单个非公共构造方法
Constructor getDeclaredConstructor(类... parameterTypes) :返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定类函数。
Constructor[] getDeclaredConstructors() :返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类 。
注意:如果是获取非公共资源,在获取之前,需要通过设置获取权限AccessibleObject类为成员变量,构造方法,成员方法,枚举提供了反射获取访问权限。
C:获取该类的Constructor对象
public T newInstance(Object... initargs) :创建由此 类对象表示的类的新实例。
D:设置
Object obj = con.newInstance("林青霞", 27, "北京");
3,获取成员方法
A:获取成员方法
方法 getMethod(String name, 类... parameterTypes) :返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。
方法[] getMethods() :返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。
B:获取全部的成员方法单个非公共成员方法
方法 getDeclaredMethod(String name, 类... parameterTypes) :返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。
方法[] getDeclaredMethods() :返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。
注意同上
C:获取该类的Constructor对象
public T newInstance(Object... initargs) :创建由此 类对象表示的类的新实例。
D:调用
public Object invoke(Object obj,Object... args)
实例:
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class c = Class.forName("cn.itcast_01.Person");
Constructor con = c.getConstructor();
Object obj = con.newInstance();
Method m1 = c.getMethod("show");
m1.invoke(obj);
System.out.println("----------");
Method m2 = c.getMethod("method", String.class);
m2.invoke(obj, "hello");
System.out.println("----------");
Method m3 = c.getMethod("getString", String.class, int.class);
Object objString = m3.invoke(obj, "hello", 100);
System.out.println(objString);
System.out.println("----------");
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj);
}}
4,获取枚举(查API,写类了)
JDK动态代理是基于反射实现,效果是代理类方法,当调用该被代理的类调用其方法时,在这个方法的前面加点什么,后面加点什么。
1,实现步骤:
A:创建代理类,实现InvocationHandler接口并重写invoke方法
public class MyInvocationHandler implements InvocationHandler {
private Object target; // 代理的目标对象
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
//参数proxy表示代理类,method代理的方法,args参数
throws Throwable {
System.out.println("权限校验");
Object result = method.invoke(target, args);
System.out.println("日志记录");
return result; // 返回的是代理对象
}
}
B:实例化代理类,将被代理类作为参数传入代理实例化类。
C:获取代理对象实例
public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
D:调用
实例:
被代理类接口
public interface StudentDao {
public abstract void login();
public abstract void regist();
}
被代理类接口实现类
public class StudentDaoImpl implements StudentDao {
@Override
public void login() {
System.out.println("登录功能");
}
@Override
public void regist() {
System.out.println("注册功能");
}}
代理类
public class MyInvocationHandler implements InvocationHandler {
private Object target; // 目标对象
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("权限校验");
Object result = method.invoke(target, args);
System.out.println("日志记录");
return result; // 返回的是代理对象
}}
测试类:
public class Test {
public static void main(String[] args) {
StudentDao sd = new StudentDaoImpl();
MyInvocationHandler handler2 = new MyInvocationHandler(sd);
StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass()
.getClassLoader(), sd.getClass().getInterfaces(), handler2);
proxy2.login();
proxy2.regist();
}
}