【Java】反射概述与详解

news2024/11/26 11:02:11

 

 

目录

引言 

一、概述

二、获取Class对象 

三、反射获取构造方法 

代码示例:

四、反射获取成员变量

代码示例:

五、反射获取成员方法

代码示例:

结语


引言 

Java中的反射(Reflection)是一种强大的机制,允许程序在运行时检查和操作其结构和行为。通过反射,程序可以动态地获取类的信息、调用方法、访问字段和创建对象。


一、概述

反射提供了一种在运行时检查类、接口、字段和方法的能力。通过反射,程序可以动态地:

  1. 获取类的所有属性和方法。
  2. 创建类的实例。
  3. 调用类的方法。
  4. 修改类的字段值。

二、获取Class对象 

在Java中,Class对象表示类和接口的元数据。获取Class对象有三种主要方式: 

通过类名获取 

Class<?> clazz = MyClass.class;

通过对象获取

MyClass obj = new MyClass();  
Class<?> clazz = obj.getClass();

通过全限定类名获取(使用Class.forName):

try {  
    Class<?> clazz = Class.forName("com.example.MyClass");  
} catch (ClassNotFoundException e) {  
    e.printStackTrace();  
}

注意:一般来说反射创建class对象通过全限定类名获取最为常用,其第一种通过类名获取常用作为参数来传递,例如:synchronized(类名.class){} 中的锁对象常用这种方式指定。


三、反射获取构造方法 

方法名说明
Constructor<?>[] getConstructors()获得所有的构造(只能public修饰)
Constructor<?>[] getDeclaredConstructors() 获得所有的构造(包含private修饰)
Constructor<T> getConstructor(Class<?>... parameterTypes)获取指定构造(只能public修饰)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)获取指定构造(包含private修饰)
newInstance创建对象
setAccessible临时取消权限检验

其代码中所用到的Paper类:

import java.io.IOException;

public class Paper {
    private String name;
    private int age;
    public String address;

    public String getAddress() {
        return address;
    }

    public Paper(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Paper() {
    }

    public Paper(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private Paper(String name) {
        this.name = name;
    }

    protected Paper(int age) {
        this.age = age;
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    private String eat(String something) throws IOException,NullPointerException,ClassCastException {
        System.out.println("在吃" + something);
        return "吃饱了";
    }

    private void sleep() {
        System.out.println("正在睡觉");
    }

    public String toString() {
        return "Paper{name = " + name + ", age = " + age + "}";
    }
}

代码示例:

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

public class ReflectConstructor {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取class对象
        Class<?> aClass = Class.forName("com.pjk.a1024reflect.Paper");

        //获取构造方法
        //1.获取所有的公共构造方法
        Constructor<?>[] cons1 = aClass.getConstructors();
        for (Constructor<?> constructor : cons1) {
            System.out.println(constructor);
        }
        //2.获取所有的构造方法
        Constructor<?>[] cons2 = aClass.getDeclaredConstructors();
        for (Constructor<?> constructor : cons2) {
            System.out.println(constructor);
        }
        //3.获取单个的公共构造方法
        // ()代表无参
        // (String.class)代表带一个String参数的有参构造
        Constructor<?> con1 = aClass.getConstructor();
        System.out.println(con1);
        //4.获取单个的构造方法
        Constructor<?> con2 = aClass.getDeclaredConstructor(String.class);
        System.out.println(con2);
        Constructor<?> con3 = aClass.getDeclaredConstructor(int.class);
        System.out.println(con3);

        System.out.println(con2.getName());
        System.out.println(con2.getModifiers());

        System.out.println("-------------------------------------------------");

        //利用获取出来的构造方法创建对象
        //1.利用公共构造创建对象
        Paper p1 = (Paper) con1.newInstance();
        System.out.println(p1);
        //2.利用非公共构造创建对象
        //暴力反射:表示临时取消权限检验
        con2.setAccessible(true);
        Paper p2 = (Paper) con2.newInstance("zhangsan");
        System.out.println(p2);
        Paper p3 = (Paper) con3.newInstance(18);
        System.out.println(p3);
    }
}

四、反射获取成员变量

方法名说明
Field[] getFields()返回所有成员变量对象的数组(只能拿public的)
Field[] getDeclaredFields()返回所有成员变量对象的数组,存在就能拿到
Field getField(String name)返回单个成员变量对象(只能拿public的)
Field getDeclaredField(String name)返回单个成员变量对象,存在就能拿到
void set(Object obj, Object value)赋值
Object get(Object obj)获取值
setAccessible临时取消权限检验

代码示例:

import java.lang.reflect.Field;

public class ReflectField {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //获取class对象
        Class<?> aClass = Class.forName("com.pjk.a1024reflect.Paper");

        //利用反射获取成员变量
        //1.获取所有公共成员变量
        Field[] fields1 = aClass.getFields();
        for (Field field : fields1) {
            System.out.println(field);
        }
        //2.获取所有成员变量
        Field[] fields2 = aClass.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }
        //3.获取单个公共成员变量
        Field address = aClass.getField("address");
        System.out.println(address);
        //4.获取单个成员变量
        Field name = aClass.getDeclaredField("name");
        System.out.println(name);

        //获取成员变量的修饰符
        System.out.println(name.getModifiers());

        //获取成员变量记录的值
        Paper p = new Paper("洁柔", 10, "广东");
        //暴力反射:表示临时取消权限检验
        name.setAccessible(true);
        String n = (String) name.get(p);
        System.out.println(n);

        //修改对象里面记录的值
        name.set(p, "维达");
        System.out.println(p);
    }
}

五、反射获取成员方法

方法名说明
Method[] getMethods()返回所有成员方法对象的数组(只能拿public的)
Method[] getDeclaredMethods()返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name, Class<?>... parameterTypes)返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod(String name, Class<?>... parameterTypes)返回单个成员方法对象,存在就能拿到
Object invoke(Object obj, Object... args)运行方法
setAccessible临时取消权限检验

注意:其中getMethods()获取成员方法时,包含了其父类的所有public公共方法。

代码示例:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class ReflectMethod {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //获取class对象
        Class<?> aClass = Class.forName("com.pjk.a1024reflect.Paper");

        //利用反射获取成员方法
        //1.获取所有公共成员方法(包含父类的公共成员方法)
        Method[] methods1 = aClass.getMethods();
        for (Method method : methods1) {
            System.out.println(method);
        }
        //2.获取所有的方法
        Method[] methods2 = aClass.getDeclaredMethods();
        for (Method method : methods2) {
            System.out.println(method);
        }
        //3.获取单个方法
        Method method = aClass.getDeclaredMethod("eat", String.class);
        //获取方法的形参
        Parameter[] parameters = method.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }
        //获取方法抛出的异常
        Class<?>[] exceptionTypes = method.getExceptionTypes();
        for (Class<?> exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }

        //方法运行
        /*
        * invoke:运行方法
        * invoke(Object obj,Object... args)
        * 参数一:用obj对象调用该方法
        * 参数二:调用方法所需形参(没有就不写)
        * */
        Paper p = new Paper("洁柔", 10, "东莞");
        method.setAccessible(true);
        String kfc = (String) method.invoke(p, "KFC");
        System.out.println(kfc);
    }
}

结语

  • 性能:反射通常比直接代码调用慢,因为它涉及额外的检查和类型转换。
  • 安全性:反射可以绕过Java的访问控制机制,可能导致意外的副作用或安全问题。
  • 异常处理:反射操作可能抛出多种检查异常(如ClassNotFoundException、NoSuchMethodException、IllegalAccessException等),需要妥善处理。

掌握反射,Java开发者可以编写更加灵活和动态的代码,但也需要谨慎使用,以避免潜在的性能和安全问题。 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

热门的四款PDF合并工具大比拼!!!

在现代的数字化办公环境中&#xff0c;PDF文件已经成为了一种重要的文件格式&#xff0c;用于保存和共享各种类型的文档。然而&#xff0c;有时候我们需要将多个PDF文件合并成一个文件&#xff0c;这时候就离不开好用的PDF合并工具了。选择一个好的PDF合并工具是一个长期的投资…

Python基于OpenCV的实时疲劳检测

2.检测方法 1&#xff09;方法 与用于计算眨眼的传统图像处理方法不同&#xff0c;该方法通常涉及以下几种组合&#xff1a; 1、眼睛定位。 2、阈值找到眼睛的白色。 3、确定眼睛的“白色”区域是否消失了一段时间&#xff08;表示眨眼&#xff09;。 相反&#xff0c;眼睛长…

【Power Query】List.Select 筛选列表

List.Select 筛选列表 ——在列表中返回满足条件的元素 List.Select(列表,判断条件) 不是列表的可以转成列表再筛选&#xff0c;例如 Record.ToList 不同场景的判断条件参考写法 (1)单条件筛选 列表中小于50的数字 List.Select({1,99,8,98,5},each _<50) (2)多条件筛…

红黑树(Java数据结构)

前言&#xff1a; 红黑树的学习需要大家对二叉搜索树与AVL树有深刻的理解&#xff0c;如果话没有看过我对二叉搜索树与AVL树的讲解的铁子们可以先看看上一篇文章&#xff1a;二叉搜索树与AVL树(java数据结构)-CSDN博客 红黑树&#xff1a; 什么是红黑树&#xff1f; 红黑树&a…

CenterTrack算法详解

背景&#xff1a; 早期追踪器在缺乏强的低水平线索下&#xff0c;容易失败检测后跟踪的模型依赖于检测器&#xff0c;且需要一个单独的阶段匹配关联策略的时间长 简介&#xff1a; 基于点的跟踪思想&#xff0c;通过预测目标的中心点来进行跟踪&#xff0c;同时实现检测与跟…

LLM在Reranker任务上的最佳实践?A simple experiment report(with code)

知乎&#xff1a;车中草同学(已授权)链接&#xff1a;https://zhuanlan.zhihu.com/p/987727357 引言 在BERT时代&#xff0c;对于Reranker任务&#xff0c;我们使用encoder-only的BERT为基座&#xff0c;拼接query和doc输入到BERT中去&#xff0c;在使用CLS的向量通过一个MLP&a…

身份证识别JAVA+OPENCV+OCR

一、相关的地址 https://github.com/tesseract-ocr/tessdata Releases - OpenCV opencv要装好&#xff0c;我装的是4.5.3的&#xff0c;最新版的没试过。 tessdata就下载了需要用的。好像还有best和fast的版本&#xff0c;我试了一下报错&#xff0c;不知道是不是版本不支持…

华为配置 之 远程管理配置

目录 简介&#xff1a; 知识点&#xff1a; Telnet远程管理 &#xff08;1&#xff09;配置接口IP并确保R1和R2处于同一个网段 &#xff08;2&#xff09;使用password认证模式远程登录 &#xff08;3&#xff09;使用AAA认证模式远程登录 SSH远程管理 &#xff08;1&a…

基于springboot的网上服装商城推荐系统的设计与实现

基于springboot的网上服装商城推荐系统的设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xf…

【deathStarBench】2.安装k8s集群

安装docker 通过以下命令安装docker&#xff1a; sudo yum install docker-ce-26.1.4 docker-ce-cli-26.1.4 containerd.io随后通过查看docker --version&#xff0c;可以确定是否安装的版本一样 启动docker systemctl start docker && systemctl enable docker.se…

《纳瓦尔宝典:财富和幸福指南》读书随笔

最近在罗胖的得到听书中听到一本书&#xff0c;感觉很有启发&#xff0c;书的名字叫《纳瓦尔宝典》&#xff0c;从书名上看给人的感觉应该财富知识类、鸡汤爆棚哪类。纳瓦尔&#xff0c;这个名字之前确实没有听说过&#xff0c;用一句话介绍一下&#xff0c;一个印度裔的硅谷中…

【LeetCode】修炼之路-0006-Zigzag Conversion (Z 字形变换)【python】

题目 The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) P A H N A P L S I I G Y I R And then read line by line: “PAHNAPLSIIGYIR” …

荣耀电脑管家-系统重装之查询设备序列号

winr输入cmd&#xff0c;再命令行中输入 wmic bios get serialnumber 如下所示

代码随想录算法训练营第六天|454四数相加II、 383赎金信、15三数之和、18四数之和

day06 1. 454四数相加II 首先定义 一个unordered_map&#xff0c;key放a和b两数之和&#xff0c;value 放a和b两数之和出现的次数。遍历大A和大B数组&#xff0c;统计两个数组元素之和&#xff0c;和出现的次数&#xff0c;放到map中。定义int变量count&#xff0c;用来统计 …

YAML格式校验API:免费工具的使用指南

YAML&#xff08;YAML Ain’t Markup Language&#xff09;是一种人类可读的数据序列化格式&#xff0c;广泛用于配置文件、数据交换等场景。由于其简洁的语法和良好的可读性&#xff0c;YAML 在开发和运维领域中越来越受到欢迎。然而&#xff0c;在使用 YAML 时&#xff0c;格…

Xcode文件默认存储位置-使用c++file保存文件默认路径以及设置为路径为当前项目路径

Xcode文件默认存储位置-使用cfile保存文件默认路径以及设置为路径为当前项目路径 1.概述 使用Xcode工具开发时候&#xff0c;遇到C调用file创建文件后&#xff0c;在当前项目中找不到文件路径。这是由于xcode会将文件保存到默认设置的路径。下面是查看文件默认存储路径和修改…

数组中的算法

目录 1.什么是数组 2.数组上的算法 2.1二分查找算法 什么是二分查找算法&#xff1f; 算法步骤 算法时间复杂度 一个问题 例题 题目分析 解题代码 2.2双指针法 什么是双指针法&#xff1f; 例题 题目分析 解题代码 1.什么是数组 数组是在一块连续的内存空间…

C++,STL 047(24.10.24)

内容 对set容器的元素进行查找与统计。 运行代码 #include <iostream> #include <set>using namespace std;void printSet(set<int> &s) {for (set<int>::iterator it s.begin(); it ! s.end(); it){cout << *it << " ";…

linux-牛刀小试

题目一&#xff1a; 1.第一问 首先创建用户tab在超级用户root的终端输入useradd tab 切换到tab用户&#xff1a; 推出重新登录到tab用户或者su – tab切换到tab用户 2.第二问 在桌面创建SHEGNCHAN目录 在SHENGCHAN文件夹下创建相应的文件&#xff1a; 3.第三问 首先&#…

哈希表【闭散列/开散列】

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;C/C 目录 一、unordered系列关联式容器 &#x1f31f;unordered_map ⭐unordered_map接口说明 二、底层结构 &#x1f31f;哈希概念 &#x1f31f;哈希冲突 &#x1f31f;哈希函数 &#x1f3…