java反射

资料来源:https://blog.csdn.net/zhangchen124

一,方式机制

       A:概念:

        JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;public、protected、private。(面向对象),private私有的,不能访问。这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

        B:原理:要知道方式机制之前,需要知道类的加载。类在运行过程中,会被加载进jvm,jvm将java文件编译成.class文件。而反射就是基于.class文件来实现的。一个类在运行过程中,会生成对应的.class文件,通过对.class文件可以获取该类的成员变量,构造方法,成员方法。

java反射_第1张图片

java反射_第2张图片

这里需要类加载器的功能实现对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动态代理

 

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();
	}
}

 

你可能感兴趣的:(java深入学习)