java反射理解,通过反射获取并修改类的对象,方法和属性

java 专栏收录该内容
17 篇文章 0 订阅

反射有什么用?

能在程序运行期间动态加载一个完全未知的类

显然可以提高java灵活性和增加应用场景

核心

Class c=Class.forName("reflection.User");

这里声明一个类的对象(注意Class中c是大写,class是关键字)
然后获取路径(包名+类名),这样c虽然不是User类,但是就相当于一面镜子
可以通过c获得对象,所以称为“反射”

说明

下面举例说明,这是包的结构,这三个类我们一一构造
在这里插入图片描述
首先我们构建一个User类,作为实验

package reflection;

public class User {
    private String name="cs";
    private String sex;
    private int age;
    public String address;
    public User(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    public User(){};
    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

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

注意:
1、需要反射的对象,我们称为JavaBean,他一定要有一个无参构造器(反射通过无参构造器获取对象)
2、我们给name赋了初值cs,address没有任何方法;作为对照

Test.java

package reflection;

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

public class Test {
    public static void main(String [] args) throws NoSuchMethodException {
        String path="reflection.User";
        try {
            Class <?>clazz=Class.forName(path);
            System.out.println(clazz.getSimpleName());
            
            //Field[] fields=clazz.getFields();//只能获得public修饰的属性
            Field[] fields=clazz.getDeclaredFields();//可以获得所有属性
            System.out.println(fields.length);

            Method[] methods=clazz.getDeclaredMethods();
            for(Method method:methods){
                System.out.println("方法有"+method);
                
            }

            Constructor [] constructors=clazz.getDeclaredConstructors();
            Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class);
            System.out.println("获得构造器"+c);
            for (Constructor constructor:constructors){
                System.out.println("构造器有"+constructor);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

这里会看到很多陌生的方法 field,method,constructor
他们分别对应类中的属性,方法,构造器
也就是说,可以通过这三个方法获取到类
在这里插入图片描述
这是打印结果,打印了属性的数量,方法的具体名称,构造器,其中获得构造器表示在getDeclaredConstructor方法中加入构造器名和对应的参数属性(因为会有同名构造器),就可以获得目标构造器,也可以通过这个方法获得目标普通方法

当然了上面的虽然能获取,但是其实没有太多作用,我们需要的是获取具体内容并修改

Test2.java

package reflection;


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

//这个注解可以避免代码警告
@SuppressWarnings("all")
public class Test2 {
    public static void main(String[] args)  {
        String path="reflection.User";
       
        User user= null;
        //以下方法都是反射API
        try {
        
            Class clazz=Class.forName(path);
            //通过newInstance(),调用无参构造方法,获取到user的对象.
            //因此javabean必须要有无参构造方法
            user = (User) clazz.getDeclaredConstructor().newInstance();
            //也可以调用其他构造器
            //先构造目标构造器,然后通过目标构造器获得相应的类的对象,以及修改属性
            Constructor constructor=clazz.getDeclaredConstructor(String.class,String.class,int.class);
            user= (User) constructor.newInstance("陈松","男",18);
            System.out.println(user.getName());
            
            //调用普通方法
            //用method设置需要调用的方法名和类型(避免重载的同名方法混淆),
            User u3= (User) clazz.getDeclaredConstructor().newInstance();
            Method method=clazz.getDeclaredMethod("setName", String.class);
            //然后用invoke激活该方法,参数是对象名和方法参数
            method.invoke(u3,"陈松u3");
            System.out.println(u3.getName());
            
            
            //调用并操作属性,使用field获取对应属性,然后跳过检测,在field中设置新数据
            User u4=(User)clazz.getDeclaredConstructor().newInstance();
            Field field=clazz.getDeclaredField("name");
            //我们这里是操作私有属性,所以是用setAccessible方法跳过私有检测
            field.setAccessible(true);
            field.set(u4,"陈松u4");
            System.out.println(u4.getName());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

在代码中我已经写了大量注释,就不再赘述
这是输出
在这里插入图片描述

  • 4
    点赞
  • 0
    评论
  • 23
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p> <span style="font-size:16px;">一、课程简介</span> </p> <p> <span style="font-size:14px;">这是</span><span><span style="color:#E56600;font-size:14px;">『</span><span style="color:#E56600;font-size:14px;">Java学习指南系列</span><span style="color:#E56600;font-size:14px;"></span><span style="color:#E56600;font-size:14px;">』</span></span><span style="font-size:14px;">第18篇教程 Java开发高级课程介绍反射机制、注解框架设计一般性原理。</span> </p> <br /> <p> <span style="font-size:16px;">二、主要内容 </span> </p> <p> <span style="font-size:14px;">本篇包含以下内容:</span> </p> <p> <span style="font-size:14px;">* 使用反射机制读取Class中字段信息</span> </p> <p> <span style="font-size:14px;">* 使用反射<span style="font-size:14px;">机制</span>对Class中方法进行调用</span> </p> <p> <span style="font-size:14px;">* 以JSON与POJO转换为例演示反射机制运用</span> </p> <p> <span style="font-size:14px;">* 自定义注解语法</span> </p> <p> <span style="font-size:14px;">* 使用反射机制读取注解信息</span> </p> <p> <span style="font-size:14px;">* 以反射注解为基础演示数据库SQL自动生成</span> </p> <p> <span style="font-size:14px;">* 注解默认值默认注解元注解内置注解</span> </p> <span style="font-size:14px;">* 以全局实例管理为例演示一般性框架设计方法</span><br /> <br /> <p> <span style="font-size:16px;">三、课程体系</span> </p> <p> <span style="font-size:14px;color:#E56600;">〖Java学习指南〗</span><span style="font-size:14px;">系列</span><span style="font-size:14px;">:包含入门与进阶语法Swing桌面开发安卓开发JavaFX开发网络通信Socket数据结构与算法等课程。</span> </p> <p> <span style="font-size:14px;color:#E56600;">〖网站开发〗</span><span style="font-size:14px;color:#E56600;">系列</span><span style="font-size:14px;"><span style="color:#E56600;">:</span>包含网页基础、网站入门、数据库、网站中级、FreeMarker、网站高级、项目应用、MyBatis、Redis等课程。</span> </p>
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值