Java反射使用的详细介绍

这篇具有很好参考价值的文章主要介绍了Java反射使用的详细介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

反射

反射基本介绍

反射概述:

反射认为类的每一个成份都是一个对象, 对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分。

在运行时,可以直接得到这个类的构造器对象:Constructor

在运行时,可以直接得到这个类的成员变量对象:Field

在运行时,可以直接得到这个类的成员方法对象:Method

这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制。

反射的关键:

反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分

HelloWorld.java -> javac -> HelloWorld.class
Class c = HelloWorld.class;

反射获取类对象

反射的第一步: 获取Class类的对象

Java反射使用的详细介绍

获取Class类对象的三种方式:

方式一:Class c1 = Class.forName(“全限名”);

全限名 = 包名 + 类名

public static void main(String[] args) throws Exception {
    // 1. 方式一: 通过Class中的一个静态方法forName(全限名: 包名+类名)
    Class c1 = Class.forName("com.chenyq.d2_reffect_class.Student");
    System.out.println(c1); // class com.chenyq.d2_reffect_class.Student
}

方式二:Class c2 = 类名.class

public static void main(String[] args) throws Exception {
    // 2. 方式二: 直接通过类名.class获取Class对象
    Class c2 = Student.class;
    System.out.println(c2); // class com.chenyq.d2_reffect_class.Student
}

方式三:Class c3 = 对象.getClass();

public static void main(String[] args) throws Exception {
    // 3. 方式三: 通过对象.getClass()获取
    Student stu = new Student(); // 创建一个对象
    Class c3 = stu.getClass();
    System.out.println(c3); // class com.chenyq.d2_reffect_class.Student
}

反射获取构造器对象

流程如下:

Java反射使用的详细介绍

使用反射技术获取构造器对象并使用

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。

Class类中用于获取构造器的方法如下:

方法 说明
getConstructors() 返回所有构造器对象的数组(只能拿public的)
getDeclaredConstructors() 返回所有构造器对象的数组,存在就能拿到
getConstructor(Class<?>… parameterTypes) 返回指定的单个构造器对象(只能拿public的)
getDeclaredConstructor(Class<?>… parameterTypes) 返回指定的单个构造器对象,存在就能拿到

演示代码:

定义一个学生类Student测试

public class Student {
    private String name;
    private int age;

    private Student() {
        System.out.println("无参构造器执行");
    }

    public Student(String name) {
        System.out.println("有参构造器执行");
        this.name = name;
    }
  
    public Student(String name, int age) {
        System.out.println("有参构造器执行");
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

getConstructors()获取全部public修饰的构造器

public static void main(String[] args) {
    // 1. 获取Class类的对象
    Class c = Student.class;

    // 2. 获取全部public修饰的构造器
    Constructor[] constructors = c.getConstructors();
    for (Constructor constructor : constructors) {
        System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());
    }
}

getConstructors()获取全部构造器包括private修饰的构造器

public static void main(String[] args) {
    // 1. 获取Class类的对象
    Class c = Student.class;

    // 2. 获取全部构造器包括private修饰的构造器
    Constructor[] constructors = c.getDeclaredConstructors();
    for (Constructor constructor : constructors) {
        System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());
    }
}

getConstructor()返回指定的单个构造器(public修饰的);

public static void main(String[] args) throws Exception {
    // 1. 获取Class类的对象
    Class c = Student.class;

    // 获取指定有参构造器
    Constructor constructor = c.getConstructor(String.class, int.class);
    System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());
}

getDeclaredConstructor()返回指定的单个构造器(包括private修饰的)

public static void main(String[] args) throws Exception {
    // 1. 获取Class类的对象
    Class c = Student.class;

    // 获取指定无参构造器
    Constructor constructor1 = c.getDeclaredConstructor();
    System.out.println(constructor1.getName() + "--->" + constructor1.getParameterCount());
    // 获取指定有参构造器
    Constructor constructor2 = c.getDeclaredConstructor(String.class);
    System.out.println(constructor2.getName() + "--->" + constructor2.getParameterCount());
}

获取构造器的作用: 依然是初始化一个对象返回。

Constructor类中用于创建对象的方法如下:

setAccessible作用, 如果遇到私有构造器可以使用setAccessible方法暴力反射, 将权限打开(只打开一次)

符号 说明
newInstance(Object… initargs) 根据指定的构造器创建对象
setAccessible(boolean flag) 设置为true,表示取消访问检查,进行暴力反射

获取构造器演示代码:

无参私有构造器创建对象

public static void main(String[] args) throws Exception {
    // 1. 获取Class类的对象
    Class c = Student.class;

    // 获取指定无参构造器
    Constructor constructor1 = c.getDeclaredConstructor();
    System.out.println(constructor1.getName() + "--->" + constructor1.getParameterCount());

    // 操作私有构造器需要暴力反射打开权限
    constructor1.setAccessible(true);
    // 利用构造器创建对象
    Student stu = (Student) constructor1.newInstance();
    System.out.println(stu); // Student{name='null', age=0}
}

公开有参构造器创建对象

public static void main(String[] args) throws Exception {
    // 1. 获取Class类的对象
    Class c = Student.class;

    // 获取指定有参构造器
    Constructor constructor2 = c.getDeclaredConstructor(String.class);
    System.out.println(constructor2.getName() + "--->" + constructor2.getParameterCount());

    Student stu2 = (Student) constructor2.newInstance("chenyq");
    System.out.println(stu2); // Student{name='chenyq', age=0}
}

反射获取成员变量对象

流程如下:

Java反射使用的详细介绍

利用反射技术获取成员变量并使用:

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。

Class类中用于获取成员变量的方法如下:

方法 说明
getFields() 返回所有成员变量对象的数组(只能拿public的)
getDeclaredFields() 返回所有成员变量对象的数组,存在就能拿到
getField(String name) 返回单个成员变量对象(只能拿public的)
getDeclaredField(String name) 返回单个成员变量对象,存在就能拿到

获取成员变量演示代码:

首先还是定义一个Student类进行测试

public class Student {
    private String name;
    private int age;
    public static String schoolName;
    public static final String COUNTTRY = "中国";

    private Student() {
        System.out.println("无参构造器执行");
    }

    public Student(String name) {
        System.out.println("有参构造器执行");
        this.name = name;
    }

    public Student(String name, int age) {
        System.out.println("有参构造器执行");
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

getFields()方法, 返回public修饰的所有成员变量对象的数组

public static void main(String[] args) {
    // 1. 创建Class类对象
    Class c = Student.class;

    // 2. 获取全部成员变量的对象
    Field[] fields = c.getFields();
    for (Field field : fields) {
        System.out.println(field.getName()); // schoolName COUNTTRY
    }
}

getDeclaredFields()方法, 返回所有成员变量对象的数组

public static void main(String[] args) {
    // 1. 创建Class类对象
    Class c = Student.class;

    // 2. 获取全部public修饰的变量
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        System.out.println(field.getName()); // name age schoolName COUNTTRY
    }
}

getField()方法, 根据名称获取单个public修饰的代码

public static void main(String[] args) throws Exception {
    // 1. 创建Class类对象
    Class c = Student.class;

    // 2. 获取单个public修饰的变量
    Field field = c.getField("schoolName");
    System.out.println(field.getName()); // schoolName
}

getDeclaredField()方法, 根据名称获取单个任何修饰符修饰的代码

public static void main(String[] args) throws Exception {
    // 1. 创建Class类对象
    Class c = Student.class;

    // 2. 获取单个private修饰的变量
    Field field = c.getDeclaredField("name");
    System.out.println(field.getName()); // name
}

获取成员变量的作用: 依然是在某个对象中取值、赋值

Field类中用于取值、赋值的方法:

Object obj: 要赋值的对象

符号 说明
set(Object obj, Object value) 赋值
get(Object obj) 获取值, 返回Object类型。
setAccessible(boolean flag) 设置为true,表示取消访问检查,进行暴力反射
public static void main(String[] args) throws Exception {
    // 创建Class类对象
    Class c = Student.class;

    // 获取单个private修饰的变量
    Field fName = c.getDeclaredField("name");
    System.out.println(fName.getName()); // name

    // 操作私有变量同样需要暴力反射
    fName.setAccessible(true);
    // 创建一个学生对象
    Student stu = new Student();
    // 赋值
    fName.set(stu, "abc");
    // 获取值, 返回类型是Object, 需要强转回字符串
    String name = (String) fName.get(stu);
    System.out.println(name); // abc
}

注意: 反射可以破坏封装性,私有的也可以执行了

反射获取方法对象

Java反射使用的详细介绍

利用反射技术获取方法对象并使用:

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。

Class类中用于获取成员方法的方法:

方法 说明
getMethods() 返回所有成员方法对象的数组(只能拿public的)
getDeclaredMethods() 返回所有成员方法对象的数组,存在就能拿到
getMethod(String name, Class<?>… parameterTypes) 返回单个成员方法对象(只能拿public的)
getDeclaredMethod(String name, Class<?>… parameterTypes) 返回单个成员方法对象,存在就能拿到

获取成员方法对象的演示代码

定义如下学生类测试

public class Student {
    private void running(String name) {
        System.out.println(name + "学生在跑步");
    }

    public void eating() {
        System.out.println("学生在吃饭");
    }

    public void swimming() {
        System.out.println("学生在游泳");
    }
}

getMethods()方法, 获取所有public修饰的成员方法

public static void main(String[] args) {
    // 1. 获取类对象
    Class c = Student.class;

    // 2. 获取所有public修饰的成员方法
    Method[] methods = c.getMethods();
    for (Method method : methods) {
        System.out.println(method.getName());
    }
}

getDeclaredMethods()方法, 获取所有的方法

public static void main(String[] args) {
    // 1. 获取类对象
    Class c = Student.class;

    // 2. 获取所有的成员方法
    Method[] methods = c.getDeclaredMethods();
    for (Method method : methods) {
        System.out.println(method.getName());
    }
}

getMethod()方法, 根据方法名获取public修饰的单个方法

public static void main(String[] args) throws Exception {
    // 1. 获取类对象
    Class c = Student.class;
  
    // 2. 根据方法名获取public修饰的单个方法
    Method method = c.getMethod("swimming");
    System.out.println(method.getName()); // swimming
}

getDeclaredMethod()方法, 根据方法名获取任意修饰符的单个方法

public static void main(String[] args) throws Exception {
    // 1. 获取类对象
    Class c = Student.class;

  	// 2. 根据方法名获取任意修饰符的单个方法
    Method method = c.getDeclaredMethod("running");
    System.out.println(method.getName()); // running
}

获取成员方法的作用依然是在某个对象中进行执行此方法

Method类中用于触发执行的方法:文章来源地址https://www.toymoban.com/news/detail-448017.html

符号 说明
invoke(Object obj, Object… args) 运行方法 参数一:用哪个对象调用该方法 参数二:调用方法的传递的参数(如果没有就不写) 返回值:方法的返回值(如果没有就不接返回值)
public static void main(String[] args) throws Exception {
    // 1. 获取类对象
    Class c = Student.class;
  
    // 根据方法名获取public修饰的单个方法, 有参数要声明参数的类型
    Method method = c.getDeclaredMethod("running", String.class);
    System.out.println(method.getName()); // running

    // 私有方法同样需要暴力反射打开权限
    method.setAccessible(true);
    // 创建一个Student对象
    Student stu = new Student();
    method.invoke(stu, "小黑"); // 小黑学生在跑步
}

到了这里,关于Java反射使用的详细介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MQ(消息中间件)概述及 RabbitMQ 的基本介绍

    消息队列中间件是分布式系统中重要的组件,主要解决 应用解耦,异步消息,流量削锋等 问题,实现高性能,高可用,可伸缩和最终一致性架构。流量削锋 : 削减峰值压力(秒杀,抢购) MQ(Message Queue,消息队列)是典型的生产者、消费者模型。生产者不断向消息队列中

    2024年02月12日
    浏览(47)
  • Vue 3 的概述以及 ES 6 基本语法的介绍

    本章首先介绍前端架构模式,然后在此基础上介绍 Vue 及其安装方式,接着介绍 Vue 3的新特性,最后介绍 ECMAScript6 (简称ES 6)的语法。 在学习 Vue.js之前,我们先来了解一下 MVVM (Model-View-ViewModel, 模型-视图-视图模型)模式,它是一种基于前端开发的架构模式。MVVM 最早出现于

    2024年03月22日
    浏览(42)
  • 最好用的流程编辑器bpmn-js系列之基本使用

    BPMN(Business Process Modeling Notation)是由业务流程管理倡议组织BPMI(The Business Process Management Initiative)开发的一套 标准 的业务流程建模符号规范。其目的是为用户提供一套容易理解的标准符号,这些符号作为BPMN的基础元素,将业务流程建模简单化、图形化,将复杂的建模过程

    2024年04月28日
    浏览(43)
  • Java 中注解的详细介绍及使用

    Java 注解,也称为 Java Annotations,是一种元数据(Meta-data)标记语言,它在 Java 代码中添加了额外的信息和说明。注解可以用于类、方法、变量、参数、包等各种程序成分上,以达到不同的应用场景。 Java 注解是从 Java 5 开始引入的,在当时就被广泛认为是 Java 语言一个非常重

    2024年02月03日
    浏览(53)
  • Java注解的介绍和使用详细讲解

    注解概述 : Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注。 注解的作用 : 对Java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定。 例如

    2024年01月19日
    浏览(35)
  • Java IO流 - 打印流详细使用介绍

    打印流基本使用 打印流 : 作用:打印流可以 实现更方便、更高效的打印数据到文件中去 。打印流一般是指:PrintStream,PrintWriter两个类。 可以实现 打印什么数据就是什么数据 ,例如打印整数97写出去就是97,打印boolean的true,写出去就是true。 打印流PrintStream构造器如下 : 构

    2024年02月02日
    浏览(45)
  • Java IO流 - 缓冲流的详细使用介绍

    缓冲流概述 缓冲流介绍 : 缓冲流也称为高效流、或者高级流。之前学习的字节流和字符流可以称为原始流。 作用:缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能 缓冲流分为: 字节缓存输入流、字节缓冲输出流、字符缓冲输入流、字符缓冲输出流 字节缓冲

    2024年02月01日
    浏览(36)
  • Java中TreeSet的基本介绍,细节讨论,使用注意事项,常用方法,底层源码分析

    TreeSet 是 Java 中的一个有序集合实现,它基于红黑树数据结构来存储元素, 可以保持元素的自然顺序(默认情况下升序)或者根据自定义比较器来进行排序 。下面是关于 TreeSet 的基本介绍、细节讨论、使用注意事项、常用方法以及一些底层实现细节。 基本介绍: TreeSet 是

    2024年02月11日
    浏览(42)
  • 【Java中的Thread线程的简单方法介绍和使用详细分析】

    提示:若对Thread没有基本的了解,可以先阅读以下文章,同时部分的方法已经在如下两篇文章中介绍过了,本文不再重复介绍!! 【Java中Tread和Runnable创建新的线程的使用方法】 【Java中的Thread线程的七种属性的使用和分析】 提示:以下是本篇文章正文内容,下面案例可供参

    2024年02月15日
    浏览(42)
  • 【Python beautifulsoup】详细介绍beautifulsoup库的使用方法,包括安装方式、基本用法、常用方法和技巧,以及结合lxml和parsel的具体使用场景和区别。

    Python beautifulsoup库是一个强大的Web抓取和解析库,它提供了丰富的功能和简单易用的API,可以帮助我们处理HTML和XML文档,从中提取数据,进行数据清洗和处理。beautifulsoup库基于Python标准库中的html.parser模块,同时还可以与第三方解析库lxml和parsel配合使用,提供更高效和灵活的

    2024年02月04日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包