【注解反射原理】

注解反射原理

  • 注解是结合反射来运行的
  • 注解只是相当于一个标识,不做具体的操作,具体操作是由反射来完成的

关于getFields()和getDeclaredFields()

getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
同样类似的还有getConstructors()和getDeclaredConstructors()、getMethods()和getDeclaredMethods()这两者分别表示获取某个类的方法、构造函数。

关于setAccessible(true)用法及意义

Accessable属性是继承自AccessibleObject 类.

功能是启用或禁用安全检查

演示案例

1、User.java

package com.luoqian;

public class User {
    private String name;

    private void myId(){
        System.out.println("id: 222111");
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

2、UserTest.java

package com.luoqian;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class UserTest {


    public static void main(String[] args) throws Exception {

        // 1.作用于属性上,field.setAccessible(true);
        Class<User> userClass = User.class;
        Constructor<User> constructor = userClass.getConstructor();
        User user = constructor.newInstance();
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            declaredField.set(user,"jack");
        }
        System.out.println(user.toString());  // User{name='jack'}


        // 2.作用于方法上,method.setAccessible(true);
        Method myId = userClass.getDeclaredMethod("myId", null);
        myId.setAccessible(true);
        myId.invoke(user,null);

    }
}

setAccessible具体的用处主要有两处:

  1. 作用于方法上,method.setAccessible(true);
  2. 作用于属性上,field.setAccessible(true);

将此对象的 accessible 标志设置为指示的布尔值。

值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查

值为 false 则指示反射的对象应该实施 Java 语言访问检查;

实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 ;

由于JDK的安全检查耗时较多.

所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的

package com.luoqian;
 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class Main {
    public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException {
        Method m = A.class.getDeclaredMethod("getName", new Class[] {});
        System.out.println(m.isAccessible());
        // getName是public的,猜猜输出是true还是false
 
        A a = new A();
        a.setName("Mr Lee");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            m.invoke(a, new Object[] {});
        }
        System.out.println("Simple              :" + (System.currentTimeMillis() - start));
 
        m.setAccessible(true); // 注意此处不同
        long start1 = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            m.invoke(a, new Object[] {});
        }
        System.out.println("setAccessible(true) :" + (System.currentTimeMillis() - start1));
    }
}
 
class A {
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

测试结果:

在这里插入图片描述

由此可以得出:Accessible并不是标识方法能否访问的,public的方法Accessible仍为false

使用了method.setAccessible(true)后 运行速度性能有了显著的提升

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值