Java:反射 reflection ( 概念+相关类+使用方法)

news/2024/5/19 6:59:23 标签: java, python, 开发语言, 反射, reflection

文章目录

  • 一、反射(reflection)
    • 1.概念
            • 优点:
            • 缺点
    • 2.反射的相关类
      • 1.Class类
          • 1.**反射机制的起源**
          • 2.获得类相关的方法
          • 3.获得类中属性的相关方法
          • 4.获得类中注解相关的方法
          • 5.获得类中构造器相关的方法
          • 6.获得类中方法相关的方法
      • 2.获取Class对象的三种方法:
            • 1.使用 Class.forName("类的全路径名");
            • 2.使用 .class 方法。
            • 3.使用类对象的 getClass() 方法

reflection_3">一、反射(reflection)


1.概念

  • Java的反射机制是 在运行状态中,可以知道任何一个类的所有属性和方法
  • 可以调用任意一个对象的任意方法和属性
  • 拿到之后就可以进行修改
  • 反射就是动态获取信息、动态调用对象方法的一种功能
优点:
  • 可以获得一个类的所有属性和方法,进行调用、修改。反射运用在很多主流框架
  • 提高灵活性和扩展性,降低耦合
缺点
  • 导致效率降低
  • 可读性差,不好维护

2.反射的相关类

类名用途
Class类代表类的实体,在运行的Java程序中表示类的接口
Field类代表类的成员变量、类的属性
Method类代表类的方法
Constructor类代表类的构造方法

1.Class类

1.反射机制的起源
  • Java文件被编译后会生成.class文件
  • .class文件会被JVM解析成一个对象:java.long.Class
  • 在运行时,每个java文件最终会变成Class类对象的一个实例
  • 通过反射,获取、添加、修改这个类的属性和方法,成为一个动态的类
2.获得类相关的方法
方法用途
getClassLoader()获得类的加载器
getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的)
forName(String className)根据类名返回类的对象
newInstance()创建类的实例
getName()获得类的完整路径名字

在这里插入图片描述

  • 获取Class对象,通过newInstans方法创建类的实例
java">    public static void reflectNewInstance() {        
		Class<?> classStudent = null;
        try {
            classStudent = Class.forName("reflect.Student");
            //获取Class对象
            Student student = (Student) classStudent.newInstance();
            //强转,向下转向
            System.out.println(student);//Student{name='小明', age=20}

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }  
    }
  • newInstans方法会抛出 InstantiationException, IllegalAccessException两个异常
  • 方法的返回值是T,被擦除成了Object,所以要进行强制类型转换
3.获得类中属性的相关方法

(以下方法返回值为Field相关)

方法用途
getField(String name)获得某个公有的属性对象
getFields()获得所有公有的属性对象
getDeclaredField(String name)获得某个属性对象
getDeclaredFields()获得所有属性对象
java">    // 反射私有属性
    public static void reflectPrivateField() {
        Class<?> classStudent = null;
        try {
            classStudent = Class.forName("reflect.Student");

            Field field = classStudent.getDeclaredField("name");
            field.setAccessible(true);
            //进行确定
            Student student = (Student) classStudent.newInstance();

            field.set(student,"王大锤");

            System.out.println(student);//Student{name='王大锤', age=20}


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
4.获得类中注解相关的方法
方法用途
getAnnotation(Class annotationClass)返回该类中与参数类型匹配的公有注解对象
getAnnotations()返回该类所有的公有注解对象
getDeclaredAnnotation(Class annotationClass)返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations()返回该类所有的注解对象
5.获得类中构造器相关的方法

(以下方法返回值为Constructor相关)

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

在这里插入图片描述

  • 同理,获得该类中与参数类型匹配的构造方法
  • 要传入对应构造方法中,参数类型的class对象
java">		  classStudent = Class.forName("reflect.Student");
            //获取Class对象
            Constructor<?> constructor = classStudent.getDeclaredConstructor(String.class, int.class);
            //获得该类中与参数类型匹配的构造方法

在这里插入图片描述

  • 这里是 constructor的newInstance()方法,传入初始化的参数列表
  • 添加对应的异常,并且进行强转
  • 因为是私有的构造方法,所以要调用setAccessible(true)方法,填上true 体现安全性(需要确认)
  • 反射打破了封装机制
java"> public static void reflectPrivateConstructor()   {      
	Class<?> classStudent = null;
        try {
            classStudent = Class.forName("reflect.Student");
            //获取Class对象

            Constructor<?> constructor = classStudent.getDeclaredConstructor(String.class, int.class);
            //获得该类中与参数类型匹配的构造方法
            constructor.setAccessible(true);

            Student student = (Student) constructor.newInstance("小红", 18);
            //这里是 constructor的newInstance()方法

            System.out.println(student);//Student{name='小红', age=18}

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {

        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

    }
}
6.获得类中方法相关的方法

(以下方法返回值为Method相关)

方法用途
getMethod(String name, Class…<?> parameterTypes)获得该类某个公有的方法
getMethods()获得该类所有公有的方法
getDeclaredMethod(String name, Class…<?> parameterTypes)获得该类某个方法
getDeclaredMethods()获得该类所有方法
java">    // 反射私有方法
    public static void reflectPrivateMethod() {
        Class<?> classStudent = null;
        try {
            classStudent = Class.forName("reflect.Student");
            Method method = classStudent.getDeclaredMethod("function", String.class);
            method.setAccessible(true);

            Student student = (Student) classStudent.newInstance();

            method.invoke(student,"不要吃");//不要吃

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

2.获取Class对象的三种方法:

1.使用 Class.forName(“类的全路径名”);

静态方法,前提是知道类的全路径名。

在这里插入图片描述

java">        Class<?> C1 = null;
        try {
            C1 = Class.forName("reflect.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
  • forName会抛出 ClassNotFoundException异常, ClassNotFoundException继承于Exception
  • 所以默认是一个受查异常(编译时异常),需要进行处理(JVM/手动抓取)
2.使用 .class 方法。
java"> Class<Student> C2 = Student.class;

仅适合在编译前就已经明确要操作的 Class

3.使用类对象的 getClass() 方法
java">        Student student = new Student();
        Class<? extends Student> C3 = student.getClass();
        System.out.println(C1 == C2);//true
        System.out.println(C1 == C3);//true

  • Class对象只存在一个

点击移步博客主页,欢迎光临~

偷cyk的图


http://www.niftyadmin.cn/n/5455356.html

相关文章

机器人深度学习IMU和图像数据实现焊接精细操作

在双电极气体保护金属弧焊 &#xff08;DE-GMAW&#xff09; 中&#xff0c;对焊枪和旁路电极位置的精确控制是至关重要的。为了这一过程&#xff0c;科研团队提出了安装微型惯性测量单元&#xff08;IMU&#xff09;传感器和摄像头&#xff0c;来记录焊工控制焊枪的移动和微调…

蓝桥杯刷题day10——猜灯谜【算法赛】

一、问题描述 在元宵节的活动现场&#xff0c;有一串环形排列的灯笼&#xff0c;共计 n 个。每个灯笼上伴随着一个谜底以及一个数字&#xff0c;这些数字分别为 a1,a2 ,…,an。 根据元宵节的传统&#xff0c;每个灯笼的谜底都是由相邻两个灯笼上的数字之和得出的。需要注意的…

HBase的Python API(happybase)操作

一、Windows下安装Python库&#xff1a;happybase pip install happybase -i https://pypi.tuna.tsinghua.edu.cn/simple 二、 开启HBase的Thrift服务 想要使用Python API连接HBase&#xff0c;需要开启HBase的Thrift服务。所以&#xff0c;在Linux服务器上&#xff0c;执行如…

14 mybatis转钱和查询余额(优化后)

文章目录 pom.xmlmybatis-config.xmlAccountMapper.xmlAccount.javaAccountMapper.javaAccountService.javaAccountServiceImpl.javaDButil.javaTestAccountService.java pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"ht…

Elasticsearch 面试题及参考答案:深入解析与实战应用

在大数据时代,Elasticsearch 以其强大的搜索能力和高效的数据处理性能,成为了数据架构师和开发者必备的技能之一。本文将为您提供一系列精选的 Elasticsearch 面试题及参考答案,帮助您在面试中脱颖而出,同时也为您的大数据架构设计提供实战参考。 1. 为什么要使用 Elastic…

服务器硬件基础知识、类型分类、维护管理及未来发展趋势

1. 服务器硬件概述 服务器定义和它在IT基础设施中的作用 服务器是一种强大的计算机系统&#xff0c;专门设计来处理、存储和传递数据。它通常为其他电脑或终端提供多种网络服务&#xff0c;如网页托管、电子邮件处理或数据库管理。在IT基础设施中&#xff0c;服务器扮演着中心…

【python】(16)python的字典dict按照key或value排序的不同方法

系列文章回顾 【python】(01)初识装饰器Decorator 【python】(02)初识迭代器Iterator 【python】(03)初识生成器Generator 【python】(04)python中实现多任务并发和并行的区别 【python】(05)如何使用python中的logging模块记录日志信息 【python】(06)理解Python中的 lambda 、…

ArrayList和LinkedList有什么区别?

ArrayList和LinkedList的区别 ArrayList 和 LinkedList 是 Java 中常用的两种集合类&#xff0c;它们都实现了 List 接口&#xff0c;但在内部实现和性能上有一些区别。 内部实现&#xff1a; ArrayList 使用数组实现&#xff0c;它的元素在内存中是连续存储的&#xff0c;每…