当前位置: 首页 > news >正文

Java中的反射

目录

一、认识反射

1、反射的概念

2、反射的作用

3、反射相关的类

二、反射的使用

1、Class类

2、调用类中的私有构造方法

3、使用类中的私有成员变量

4、调用类中的私有成员方法 

三、反射的优点和缺点

1、优点

2、缺点


一、认识反射

1、反射的概念

        Java的反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法;对于任意一个对象,都能够调用它的任何方法和属性。这种动态获取类的信息以及动态调用方法的功能称为Java语言的反射(reflection)机制。

2、反射的作用

        Java程序中一些对象在运行时会出现两种类型:运行时类型编译时类型,例如一个向上转型的代码:Bird bird = new Animal();其中,bird在编译时类型为Bird,运行时类型为Animal,通过反射机制就能在程序运行时发现该对象和类的真实信息。

3、反射相关的类

Class类代表类的实体,在运行的Java应用程序中表示类和接口
Field类代表类的成员变量/字段
Method类代表类的方法
Constructor类代表类的构造方法

二、反射的使用

1、Class类

        在反射之前,我们需要先拿到当前需要反射的类的Class对象,然后通过Class对象调用相关的方法,来达到反射的目的。

获得Class对象的三种方式:

(1)使用Class.forName方法("类的全路径名");

(2)使用需要反射的类名调用class方法;

(3)使用需要反射的类的对象调用getClass方法

但是通过三种方式获取的Class对象都是相同的,也就是说,一个类只有一个对应的Class对象

Class类中常用获得类相关的方法
方法作用
getClassLoader()获得类的加载器
getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象
forName(String classRoad)根据类的路径返回类的Class对象(该方法是静态成员方法)
newInstacne()创建类的实例
getName()获得类的完整路径名

2、调用类中的私有构造方法

获得类中构造器相关的方法(返回值为Constructor类型相关)

方法作用
getConstructor(Class...<?>parameterTypes)获得该类中与参数类型匹配的公有的构造方法
getConstructors()获得该类中所有公有的构造方法
getDeclaredConstructor(Class...<?>parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类中所有构造方法

示例: 

创建一个Student类:

public class Student {
    public String name;//公共的成员变量

    private int id = 1;//私有的成员变量

    public Student(){
        System.out.println("公共的构造方法");
    }

    private Student(int id){
        this.id = id;
        System.out.println("私有的构造方法");
    }

    public void func(){
        System.out.println("公共的成员方法");
    }

    private void func2(String s){
        System.out.println(s);
    }

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

在同一个包中的Test类中通过Student类私有的构造方法创建一个Student对象:

public class Test {
    public static void reflectPrivateConstructor(){
        try {
            //获得Class对象
            Class<?> c1 = Class.forName("reflect.Student");
            //调用getDeclaredField(String name)方法
            Constructor<?> constructor = c1.getDeclaredConstructor(int.class);
            //调用setAccessible(boolean)后可修改访问权限
            constructor.setAccessible(true);
            //通过Constructor对象创建Student对象
            Student student = (Student) constructor.newInstance(100);
            //输出创建好的Student对象
            System.out.println(student);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws ClassNotFoundException {
        reflectPrivateConstructor();
    }
}

代码运行结果:

 

3、使用类中的私有成员变量

获得类中字段相关的方法(返回值为Field类型相关)

方法作用
getField(String name)获得该类中某个公有的字段
getFields()获得该类中所有公有的字段
getDeclaredField(String name)获得该类中某个字段
getDeclaredFields()获得该类中所有字段

示例: 

反射Student类中的私有成员变量

public class Test {
    public static void reflectPrivateField(){
        try {
            //获得Class对象
            Class<?> c1 = Class.forName("reflect.Student");
            //getDeclaredField(String name)方法
            Field field = c1.getDeclaredField("id");
            //调用setAccessible(boolean)后可修改访问权限
            field.setAccessible(true);
            //通过Class类反射一个Student对象
            Student student = (Student) c1.newInstance();
            //修改指定Student对象的静态成员变量:id = 500
            field.set(student,500);
            //输出Student对象
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        reflectPrivateField();
    }
}

代码运行结果:

4、调用类中的私有成员方法 

获得类中方法相关的方法(返回值为Method类型相关)

方法作用
getMethod(String name,Class...<?>parameterTypes)获得该类中某个公有的方法
getMethods()获得该类中所有公有的方法
getDeclaredMethod(String name,Class...<?>parameterTypes)获得该类中某个方法
getDeclaredMethods()获得该类中所有方法

 示例: 

反射Student类中的私有成员方法

public class Test {
    public static void reflectPrivateMethod(){
        try {
            //获得Class对象
            Class<?> c1 = Class.forName("reflect.Student");
            //调用getDeclaredMethod(String name,Class...<?>parameterTypes)方法
            Method method = c1.getDeclaredMethod("func2",String.class);
            //获取私有的属性或方法一般都要调用setAccessible(boolean)方法
            method.setAccessible(true);
            //通过Class类反射一个Student对象
            Student student = (Student) c1.newInstance();
            //Method对象调用invoke方法
            //让指定的Student对象调用指定的私有方法并传参
            method.invoke(student,"通过反射机制调用Student类的私有方法");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        reflectPrivateMethod();
    }
}

代码运行结果:

三、反射的优点和缺点

1、优点

(1)对于任意一个类,都能够获得这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;

(2)增加程序的灵活性和扩展性,降低耦合性。

2、缺点

(1)使用反射会导致程序效率降低(为了获得一个类的对象,调用了Class类中的多个方法);

(2)反射机制绕过了源代码,可能会带来维护问题。

相关文章:

  • java毕业设计旅游网站设计mybatis+源码+调试部署+系统+数据库+lw
  • Java基础进阶-序列化
  • 02.3 线性代数
  • java毕业设计木材产销系统的生产管理模块mybatis+源码+调试部署+系统+数据库+lw
  • Nuxt - 自定义页面布局,<Nuxt /> 个性化多套模板(一个项目内既要有用户正常浏览的普通页面,又要存在后台管理系统布局的页面)
  • java毕业设计拉萨旅游自助民宿平台mybatis+源码+调试部署+系统+数据库+lw
  • 微信公众号查题搜题功能系统平台
  • 王道计算机组成原理课本课后习题错题总结
  • cefsharp 最新稳定版104.4.240 (chromium-104.0.5112.102)
  • Unity开发3
  • spark(day02)
  • 【我不熟悉的css】05. csc中使用变量,:root伪元素的应用
  • 03.2 线性回归的从零开始实现
  • js深复制一个数组
  • 03.3线性回归的简洁实现
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Javascript基础之Array数组API
  • LeetCode29.两数相除 JavaScript
  • Mocha测试初探
  • Mybatis初体验
  • rabbitmq延迟消息示例
  • SOFAMosn配置模型
  • ViewService——一种保证客户端与服务端同步的方法
  • windows-nginx-https-本地配置
  • 程序员最讨厌的9句话,你可有补充?
  • 从0实现一个tiny react(三)生命周期
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 和 || 运算
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 译自由幺半群
  • 栈实现走出迷宫(C++)
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 06-01 点餐小程序前台界面搭建
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ​Spring Boot 分片上传文件
  • ​香农与信息论三大定律
  • !!Dom4j 学习笔记
  • #define,static,const,三种常量的区别
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • (007)XHTML文档之标题——h1~h6
  • (2)STM32单片机上位机
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (2020)Java后端开发----(面试题和笔试题)
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)shell调试方法
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • .form文件_一篇文章学会文件上传
  • .Net CF下精确的计时器