栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【JAVA反射】反射的原理及简单使用实例

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【JAVA反射】反射的原理及简单使用实例

JAVA反射机制
    • 反射机制的概要
    • 通过反射创建类
      • 获取Class的方式
      • 通过Class实例化对象
    • 通过反射调用类方法
      • 通过Class获取类中的方法
      • 通过Method调用方法
    • 通过反射修改类属性
      • 通过Class获取属性
      • 通过Class修改对象属性

反射机制的概要

 JAVA的反射机制,就是可以通过全类名,获取当前类、调用当前类方法,以及获取或修改当前类属性的一个机制。
 总结来说:就是通过类对象来获取类信息的一个途径。
 如示例:若A类无法引用B类的话,但是又要调用B类的方法,其实就可以调用反射获取B类并且执行B类的方法。


通过反射创建类

首先认识类对象 :Class,类对象中中记录了这个类包含了哪些属性、哪些方法、以及有哪些构造方法等信息。
对于Class的话在这里不多做介绍,具体可以看这个博客:类对象详细介绍.

获取Class的方式
// A的全类名为: package.pojo.A
// 首先有以下几种方式获取类对象
Class a = Class.forName("package.pojo.A"); //参数为类的全类名
Class b = A.class;
Class c = new A().getClass();

获取了 Class 类对象之后,就可以通过类对象去调用方法、获取数据等。

通过Class实例化对象
// 通过Class类对象去实例化对象
try {
	// 这里用一种方式去获取Class,也可以用其他方式
	Class a = Class.forName("package.pojo.A");
	// 通过类对象获取默认构造器
	Constructor c = a.getConstructor();
	// 通过构造器调用构造方法完成实例化
	A a1 = (A)c.newInstance();
	// 此时已经获取到A对象,可以通过A对象做后续的事情了
} catch (Exception e) {
	e.printStackTrace();
}

通过反射调用类方法

通过Class去调用类的方法的话,应该是我日常中使用反射用的最多的一个方式了,很多时候无法引入类我都会使用反射去调用所需要的类的方法

通过Class获取类中的方法

我们可以通过 getMethod() 获取到Method对象,来调用类方法
当然还有 getDeclaredMethod() 这两个区别请看下面获取属性的方法即可

// 首先请看Class.getMethod()的源码

private Method getMethod0(String name, Class[] parameterTypes, boolean includeStaticMethods) {
	// 父接口的方法数组
	MethodArray interfaceCandidates = new MethodArray(2);
	// 获取方法的Method对象
	Method res =  privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
	// 如果不为空,说明从本类或者父类中获取到了root对象的拷贝对象,直接返回
	if (res != null)
		return res;

	// Not found on class or superclass directly
	interfaceCandidates.removeLessSpecifics();
	// 如果没从本类/父类中获取到方法,则从父接口中获取方法
	return interfaceCandidates.getFirst(); // may be null
    }

看完源码之后,其实获取Method对象的就很清晰明了的了,下面是示例

// 首先存在方法为
public String isBigData(String name, Integer number) {
	// 省略方法体
}

// 首先肯定要获取相对应的Class对象
Class a = Class.forName("package.pojo.A");

// 通过调用Class.getMethod()获取方法
// 第一个参数为方法名
// 第二个参数为方法所需参数的Class,因为目前是两个参数,所以要传递一个数组如果方法只有一个参数则传递一个参数即可
// 第三个参数,由于当前方法不是Static,不需要传递
Method isBigDataMethod = a.getMethod("isBigData",  new Class[] { String.class, int.class });
通过Method调用方法

上面已经学习过了如何通过Class获取Method方法对象,此时就可以通过此方法对象去执行方法了

调用方法主要是用到 Method.invoke() 即可

// Method.invoke()源码如下

	@CallerSensitive
    public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }
        return ma.invoke(obj, args);
    }

调用方式如下

// 省略之前步骤,获取Method对象
Method isBigDataMethod = a.getMethod("isBigData",  new Class[] { String.class, int.class });

// 由于调用A对象中的方法需要有A对象,所以先创建出来
Class a = Class.forName("package.pojo.A");
Constructor c = a.getConstructor();
Objcet a1 = c.newInstance();

// 直接调用Method.invoke()即可
// 第一个参数调用方法的对象
// 第2,3..个参数,就是调用方法所需的对象
String rtn = isBigDataMethod.invoke(a1, "value1", 3);
// 此时就直接完成了方法的调用了

通过反射修改类属性 通过Class获取属性

Class中存在两个方法可以获取类属性,分别为
Field[] getFields() / Field getField(String name)
Field[] getDeclaredFields() / Field getDeclaredField(String name)

getFields(),只能获取public的属性,无法获取其他属性,Class源码和解释如下

// 通过Member.PUBLIC参数来控制只获取public属性
@CallerSensitive
    public Field[] getFields() throws SecurityException {
        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
        return copyFields(privateGetPublicFields(null));
    }

getDeclaredFields(),则能获取public属性以及private属性,但是不能获取继承的属性

@CallerSensitive
    public Field[] getDeclaredFields() throws SecurityException {
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        return copyFields(privateGetDeclaredFields(false));
    }

则我们可以通过两种方式来获取属性

通过Class修改对象属性

既然都可以将属性获取出来了,此时也可以通过反射对对象设置属性值

// 首先通过反射来获取Class类
Class a = Class.forName("packeage.pojo.A");
// 通过Class实例化一个类
A a = (A) a.getConstructor().newInstance();
// 获取所有属性
Fields fields = a.getFields();
// 可以通过属性名称来获取Field对象
Field attrA = a.getField("属性名称");
// 直接调用Field.set(类对象Object, value)即可修改属性值
attrA.set(a, "value"); // 此时就是给a对象的attrA属性设置值了

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/350985.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号