Java反射的各种使用

1.1 首先了解些反射基本知识

指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法。这种动态获取信息,以及动态调用对象方法的功能叫java语言的反射机制。

反射的关键类就是Class类,我们一般有三种获取Class的方式:

第一种: 通过加载包路径获取class

Class c =Class.forName("com.xxxx.xxxx")

第二种: 直接通过类.class

Class c = Person.class;

第三种: 通过类实例对象获取

Person p = new Person();
Class c = p.getClass();

好了,我们拿到Class 干什么呢?Class 类里到底包含了什么?这就涉及到反射的作用了,反射有什么用呢,我们可以从网上了解到很多。举个例子,我们想通过注解获取对应的方法或者参数,这时候就可以用到反射,反射可以减少我们的代码,可以让不可能变成可能。spring源码里就是用了很多反射机制。当然我也不打算去研究反射原理,就像记录下各种用法。

我们首先看下Class到底是个什么东西,看源码吧,太多了我就不粘了,粘两个方法以示尊敬。

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {
 @CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }
    
    public T newInstance()
        throws InstantiationException, IllegalAccessException
    {
        if (System.getSecurityManager() != null) {
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
        }

        // NOTE: the following code may not be strictly correct under
        // the current Java memory model.

        // Constructor lookup
        if (cachedConstructor == null) {
            if (this == Class.class) {
                throw new IllegalAccessException(
                    "Can not call newInstance() on the Class for java.lang.Class"
                );
            }
            try {
                Class<?>[] empty = {};
                final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
                // Disable accessibility checks on the constructor
                // since we have to do the security check here anyway
                // (the stack depth is wrong for the Constructor's
                // security check to work)
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction<Void>() {
                        public Void run() {
                                c.setAccessible(true);
                                return null;
                            }
                        });
                cachedConstructor = c;
            } catch (NoSuchMethodException e) {
                throw (InstantiationException)
                    new InstantiationException(getName()).initCause(e);
            }
        }
        Constructor<T> tmpConstructor = cachedConstructor;
        // Security check (same as in java.lang.reflect.Constructor)
        int modifiers = tmpConstructor.getModifiers();
        if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            if (newInstanceCallerCache != caller) {
                Reflection.ensureMemberAccess(caller, this, null, modifiers);
                newInstanceCallerCache = caller;
            }
        }
        // Run constructor
        try {
            return tmpConstructor.newInstance((Object[])null);
        } catch (InvocationTargetException e) {
            Unsafe.getUnsafe().throwException(e.getTargetException());
            // Not reached
            return null;
        }
    }
	//省略class源码...........
}
1.2 反射常用的一些方法
public class Person {
	private String name;
	private Integer age;

	private Person(){

	}

	public Person(String name,Integer age){
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
}
@Target({ElementType.METHOD,ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Mapping {
	String value() default "";
}
1.2.1 获取类的构造函数
	Class<Person> clazz = Person.class;
	//获取所有的构造方法
	for (Constructor<?> declaredConstructor : clazz.getDeclaredConstructors()) {
	
		logger.debug("构造方法:{}", declaredConstructor.toString());
		
		//也可以获取参数类型
		Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
		
		//获取构造方法上注解信息Mapping为注解类
		Mapping annotation = declaredConstructor.getAnnotation(Mapping.class);
		logger.debug("注解信息:{}", annotation.value());
	}

	//调用构造方法
	Class<?>[] param = {String.class,Integer.class};
	Constructor<Person> declaredConstructor = clazz.getDeclaredConstructor(param);
	//访问私有构造方法
	declaredConstructor.setAccessible(true);
	Person zhangsan = declaredConstructor.newInstance("zhangsan", 1);
	logger.debug("name:{},age:{}",zhangsan.getName(),zhangsan.getAge());
	
1.2.2 获取类的方法

获取类的方法和获取构造函数基本一致,获取注解也是通过getAnnotation().

	//获取类的方法
	Method[] declaredMethods = clazz.getDeclaredMethods();
	for (Method declaredMethod : declaredMethods) {
		logger.debug("所有方法:{}", declaredMethod.toString());
	}
	//调用方法
	Person person = new Person("lisi",10);
	Class<?>[] paramT = {String.class};
	Method method = clazz.getDeclaredMethod("setName", paramT);
	//调用私有方法
	method.setAccessible(true);
	method.invoke(person,"zhangsan");
	logger.debug("person name is {}",person.getName());
1.2.2 获取类的属性
	//获取类的属性
	Field[] declaredFields = clazz.getDeclaredFields();
	for (Field declaredField : declaredFields) {
		logger.debug("所有属性:{}", declaredField.toString());
	}
	//修改属性值
	Field field = clazz.getDeclaredField("age");
	field.setAccessible(true);
	field.set(person,20);
	logger.debug("person age is {}",person.getAge());
1.2.2 获取类、方法、属性、参数上的Annotation注解值

这个其实很简单。如果想获取方法上的注解,就现获取方法Method,然后通过method.getgetAnnotation(),直接看代码:

//获取类上的
clazz.getAnnotation(Mapping.class);
//获取方法上的
Method method = clazz.getDeclaredMethod("setName", paramT);
Method.getAnnotation(Mapping.class)
//获取属性上的
Field field = clazz.getDeclaredField("age");
field.getAnnotation(Mapping.class);
//获取参数上的
for (Parameter parameter : method.getParameters()) {
	Mapping annotation = parameter.getAnnotation(Mapping.class);
}

到此,还有很多没有方法没有涉及其中,有空还是可以多多研究研究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值