反射和注解的学习

Java反射

反射

反射基本概念

首先反射是什么:Java的反射是指在运行状态中,对于任何一个类都能知道他的属性和方法,对于任何一个对象都能调用他的属性和方法

Class在java中也是一个实实在在存在的类,每个java类运行时在JVM中都表现为一个Class对象,基本数据类型在JVM中表现也是一个Class对象。每个通过Class标识的类在内存中都有且只有一个与之对应的Class对象,无论创建多少个实例依据都是一个Class对象。Class类只有私有构造函数所有Class对象都只能有JVM创建和加载。Class类的作用是运行时提供或获得对象类型信息

反射基本使用

Class的获取

User对象


public class User {
    private String userName;
    private String age;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

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

    public User() {
    }

    public User(String userName, String age) {
        this.userName = userName;
        this.age = age;
    }

    public void prepareExamination(){
        System.out.println("学生正在努力备考!!");
    }
}

Class的三种获取方式

    @Test
    public void test18() throws Exception {

//      通过类名.class获取类的反射 获取Class对象的一个引用,返回表示该对象的实际类型的Class引用。
        Class<User> userClass = User.class;
        User user = new User("张三", "19");
//      通过实例.getClass()获取类的反射
        Class<User> aClass = user.getClass();
//      通过Class.forName("类全限定类名获取反射") 获取Class对象的一个引用,但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类。
        Class<User> aClass1 = Class.forName("com.zzk.myTest.User");
    }

反射的方法

    @Test
    public void test19() throws Exception {
//      通过Class.forName("类全限定类名获取反射")
        Class<?> userClass = Class.forName("com.zzk.myTest.User");
//      获取类的全限定类名
        System.out.println("这是User类全定类名:" + userClass.getName());
//      获取类名
        System.out.println("这是User类名:" + userClass.getSimpleName());
//      通过反射创建对象实例 返回一个Oject对象,是实现“虚拟构造器”的一种途径。使用该方法创建的类,必须带有无参的构造器。
        System.out.println("这是通过反射新创建的User对象" + userClass.newInstance());
        //=========================================构造方法==============================================================
        // 通过参数类型获取public的构造方法 Constructor<T> getConstructor(Class<?>... parameterTypes)
        Constructor<?> constructor = userClass.getConstructor(String.class, String.class);

        // 获取该类的所有的public的构造方法 Constructor<?>[] getConstructors() throws SecurityException
        Constructor<?>[] constructors = userClass.getConstructors();

        // 可利用获取的构造方法创建对象
        // 例如 constructor创建对象就是使用的是 public User(String userName, String age)方法常见对象
        // 若构造方法私有可使用 实例.setAccessible(true)方法设置访问权限
        // 可使用getGenericParameterTypes()方法获取一组 type 对象,返回的就是 Constructor对象构造函数的形参类型。
        // 可使用getParameterTypes()方法获取一组 Class 对象,返回的就是 Constructor对象构造函数的形参类型。
        User newInstance = (User)constructor.newInstance("张三", "75");
        System.out.println(newInstance); //结果是 User{userName='张三', age='75', result=null}

        // =========================================获取方法=============================================================
        // 根据方法名和参数类型获取该类public的方法(包括继承自父类public的方法) Method getMethod(String name, Class<?>... parameterTypes)
        Method prepareExamination = userClass.getMethod("prepareExamination");

        // 获取该类的所有public的方法(包括继承自父类public的方法) Method[] getMethods() throws SecurityException
        Method[] methods = userClass.getMethods();

        // 根据方法名和参数获取该类的public和非public方法(默认不包括继承自父类的方法) Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        Method declaredMethod = userClass.getDeclaredMethod("prepareExamination");

        // 获取该类的所有public和非public的方法(默认不包括继承自父类的方法) Method[] getDeclaredMethods() throws SecurityException
        Method[] declaredMethods = userClass.getDeclaredMethods();

        // 可使用获得的 实例.invoke(该类实例(),参数..)执行类的方法
        // getReturnType()方法返回class对象用来描述方法返回值
        // getGenericReturnType()方法返回Type对象用来描述方法返回值
        // getParameterTypes()方法返回Class对象数组用来描述方法参数类型
        // getParameterTypes()方法返回Type对象数组用来描述方法参数类型
        // getName()方法方法名称
        // setAccessible(true)设置方法的可访问性
        // 例如:
        prepareExamination.invoke(newInstance);

        // =========================================获取属性=============================================================
        // 根据属性名称获取该类的public的属性(包括继承自父类public的属性)
        Field result = userClass.getField("result");

        // 获取该类的所有的public属性(包括继承自父类public的属性)
        Field[] fields = userClass.getFields();

        // 根据属性名称获取该类的public和非public的属性(默认不包括继承自父类属性)
        Field age = userClass.getDeclaredField("age");

        // 获取该类的所有的public属性(默认不包括继承自父类属性)
        Field[] declaredFields = userClass.getDeclaredFields();

        // 可使用set(该类实例,新值)方法来给对象设置值 使用get(类实例)来获取该属性值 getName返回该字段值
        // 如参数不可访问可使用setAccessible(true)来改变访问性
        // getType()返回Type对象来表示属性类型 getDeclaringClass()方法用来返回class对象表述属性类型
        // 例:使用get()获取该类所属值
        System.out.println(result.get(newInstance)); // null
        result.set(newInstance,80);
        System.out.println(result.get(newInstance)); // 80

        // =========================================实现接口和父类=============================================================
        // 获取该类的父类的class对象
        Class<?> superclass = userClass.getSuperclass();
        // 获取该类实现的所有接口
        Class<?>[] interfaces = userClass.getInterfaces();
        // 获取该类所有的注解
        Annotation[] annotations = userClass.getAnnotations();
反射的应用

使用反射实现java原生动态代理

java的被代理的对象必须实现接口,会代理接口中的方法

// 接口
public interface Examination {
    void prepareExamination();
}
// 实现接口
public class User implements Examination{
    @Override
    public void prepareExamination(){
        System.out.println("学生正在努力备考!!");
    }
}
// 代理handler
public class UserHandler implements InvocationHandler {

    // 初始化
    private Object object;

    public Object bind(Object object){
        this.object = object;	
        // 创建动态代理对象 参数为:使用什么类加载器加载代理类,代理对象实现接口,代理类handler
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);
    }


    // method即被代理的方法,在方法之前执行的即前置通知,后面执行的即后置通知
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        front();
        Object invoke = method.invoke(this.object, args);
        after();
        return invoke;
    }

    public void front(){
        System.out.println("学生的父母送孩子来到学校");
    }

    public void after(){
        System.out.println("学生考试结束!");
    }

}
// 看看结果把!
@Test
public void test21(){
	UserHandler userHandler = new UserHandler();
	Examination examination = (Examination) userHandler.bind(new User("张三", "45"));
	examination.prepareExamination();
}
// 输出结果
//    学生的父母送孩子来到学校
//    学生正在努力备考!!
//    学生考试结束!

参考:

https://pdai.tech/md/java/basic/java-basic-x-reflection.html

https://www.cnblogs.com/lzq198754/p/5780331.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值