Java反射,看完就会用

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

什么是反射

在说反射概念之前,我们先说另外2个概念:编译期运行期

编译期:

  • 编译期是源代码从文本形式转换为字节码的过程,这发生在Java代码被JVM执行之前。
  • 在编译期,编译器对源代码进行语法检查、类型检查、变量名解析等操作,确保代码符合Java的语法规则,并将其编译成字节码(.class文件)。
  • 编译期间的操作基于静态类型信息。编译器只能使用它在编译时了解的信息,而不能知晓运行时的具体情况。

运行期:

  • 运行期是指编译后的代码在Java虚拟机(JVM)上执行的过程。
  • 在运行期,JVM执行编译后的字节码,并进行各种运行时操作,如内存分配、垃圾回收等。

反射机制主要发生在运行期。反射允许程序在运行时动态访问和操作类、对象、方法、属性等。

使用反射,程序可以获取类的信息(如类名、方法、字段等),并可以创建对象、调用方法、修改字段值,这些都是在运行时发生的。

补充:在学习JVM内存结构时,我们知道在类信息是存放在方法区的。

反射的优缺点

优点:

在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

缺点:

(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;

(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

反射的入口:Class类

类 Class 的实例代表在运行中的 Java 应用程序中的类和接口。枚举是一种类,注解是一种接口。每个数组也属于一个类,这个类以 Class 对象的形式反映出来,这个 Class 对象被所有具有相同元素类型和维数的数组共享。Java 的基本类型(boolean、byte、char、short、int、long、float 和 double)以及关键字 void 也表示为 Class 对象。

三种方式获取Class对象

  • 通过实例对象获取Class对象

  • 通过类名.class获取Class对象

  • 通过Class.forName(String className)获取Class对象

@SpringBootTest
class DemoReflectionApplicationTests {

    @Test
    void contextLoads() throws ClassNotFoundException {
        User user = new User();
        Class<? extends User> u1 = user.getClass();
        System.out.println(u1.getName());
        System.out.println(u1.hashCode());

        Class<User> u2 = User.class;
        System.out.println(u2.hashCode());

        Class<?> u3 = Class.forName("com.example.reflection.pojo.User");
        System.out.println(u3.hashCode());
    }

}
com.example.reflection.pojo.User
1970707120
1970707120
1970707120

在运行期间,一个类只有一个Class对象产生。

获取到Class对象,我们能拿到哪些信息?

获取名称信息

// 返回Java内部使用的真正的名称
public String getName();
// 返回的名称不带包信息
public String getSimpleName();
// 返回的名称更加友好
public String getCanonicalName();
// 返回包信息
public String getPackage();
@Test
void contextLoad2() throws ClassNotFoundException {
    Class<?> u = Class.forName("com.example.reflection.pojo.User");
    System.out.println(u.getName());
    System.out.println(u.getSimpleName());
    System.out.println(u.getCanonicalName());
    System.out.println(u.getPackage());

    Class<String> s = String.class;
    System.out.println(s.getName());
    System.out.println(s.getSimpleName());
    System.out.println(s.getCanonicalName());
    System.out.println(s.getPackage());
}

结果:

com.example.reflection.pojo.User
User
com.example.reflection.pojo.User
package com.example.reflection.pojo
java.lang.String
String
java.lang.String
package java.lang, Java Platform API Specification, version 1.8

Java反射,看完就会用

获取字段信息

Class获取字段信息的方法:

// 返回所有的public字段,包括其父类的,如果没有字段,返回空数组
public Field[] getFields()
// 返回本类声明的所有字段,包括非public的,但不包括父类的
public Field[] getDeclaredFields()
// 返回本类或父类中指定名称的public字段,找不到抛出异常NoSuchFieldException
public Field getField(String name)
// 返回本类中声明的指定名称的字段,找不到抛出异常NoSuchFieldException
public Field getDeclaredField(String name)

获取到Field以后,进一步获取字段信息:

// 获取字段的名称
public String getName()
// 判断当前程序是否有该字段的访问权限
public boolean isAccessible()
// flag设为true表示忽略Java的访问检查机制,以允许读写非public的字段
public void setAccessible(boolean flag)
// 获取指定对象obj中该字段的值
public Object get(Object obj)
// 将指定对象obj中该字段的值设为value
public void set(Object obj, Object value)

// 返回字段的修饰符
public int getModifiers()
//返回字段的类型
public Class<? > getType()
//查询字段的注解信息,下一章介绍注解
public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
public Annotation[] getDeclaredAnnotations()

获取方法信息

类中定义的静态方法实例方法都算在内,用类Method表示。

//返回所有的public方法,包括其父类的,如果没有方法,返回空数组
public Method[] getMethods()
//返回本类声明的所有方法,包括非public的,但不包括父类的
public Method[] getDeclaredMethods()
//返回本类或父类中指定名称和参数类型的public方法,
//找不到抛出异常NoSuchMethodException
public Method getMethod(String name, Class<? >... parameterTypes)
//返回本类中声明的指定名称和参数类型的方法,找不到抛出异常NoSuchMethodException
public Method getDeclaredMethod(String name, Class<? >... parameterTypes)

获取到Method后,进一步获取方法的详细信息:

//获取方法的名称
public String getName()
//flag设为true表示忽略Java的访问检查机制,以允许调用非public的方法
public void setAccessible(boolean flag)
//在指定对象obj上调用Method代表的方法,传递的参数列表为args
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException

创建对象和构造方法

Class直接创建对象,调用无参构造器。

public T newInstance()

Class获取构造器:

//获取所有的public构造方法,返回值可能为长度为0的空数组
public Constructor<? >[] getConstructors()
//获取所有的构造方法,包括非public的
public Constructor<? >[] getDeclaredConstructors()
//获取指定参数类型的public构造方法,没找到抛出异常NoSuchMethodException
public Constructor<T> getConstructor(Class<? >... parameterTypes)
//获取指定参数类型的构造方法,包括非public的,没找到抛出异常NoSuchMethodException
public Constructor<T> getDeclaredConstructor(Class<? >... parameterTypes)

获取到构造器用构造器创建对象:

public T newInstance(Object ... initargs)

类型检查和转换

类型检查:

/**
* Params:
* obj – the object to check
* Returns:
* true if obj is an instance of this class
*/
public native boolean isInstance(Object obj);

类型转换:

// 将一个对象转换为由此 Class 对象所代表的类或接口。
public T cast(Object obj) 

获取Class的类型信息

Class代表的类型既可以是普通的类,也可以是内部类,还可以是基本类型、数组等,对于一个给定的Class对象,它到底是什么类型呢?可以通过以下方法进行检查:

public native boolean isArray()  //是否是数组
public native boolean isPrimitive()  //是否是基本类型
public native boolean isInterface()  //是否是接口
public boolean isEnum()  //是否是枚举
public boolean isAnnotation()  //是否是注解
public boolean isAnonymousClass()  //是否是匿名内部类
public boolean isMemberClass()  //是否是成员类,成员类定义在方法外,不是匿名类
public boolean isLocalClass()  //是否是本地类,本地类定义在方法内,不是匿名类

获取类的声明信息

//获取修饰符,返回值可通过Modifier类进行解读
public native int getModifiers()
//获取父类,如果为Object,父类为null
public native Class<? super T> getSuperclass()
//对于类,为自己声明实现的所有接口,对于接口,为直接扩展的接口,不包括通过父类继承的
public native Class<? >[] getInterfaces();
//自己声明的注解
public Annotation[] getDeclaredAnnotations()
//所有的注解,包括继承得到的
public Annotation[] getAnnotations()
//获取或检查指定类型的注解,包括继承得到的
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

对于反射这一块内容的话,其实理解起来并不是很难,但确实是很重要,所以非常建议把代码全部敲一遍。

对于编程学习来说,Coding百遍,其义自见。

仍然是不变的硬道理。

以上就是关于反射的所有内容,感谢阅读!


联系我:
https://haibin9527.gitee.io/about_me/文章来源地址https://www.toymoban.com/news/detail-761777.html

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

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

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

相关文章

  • 2023年最新CUDA安装教程,看完就会(windows版)。

    目录 前言 注意:本教程建立在您已经正确安装了显卡驱动的基础上 第一步,找到对应的CUDA版本 第二步,查看你要安装的pytorch版本对应的cuda版本(如果只需要安装cuda可以跳过) 第二步,下载cuda 第三步,安装CUDNN加速库 尾言 本文概述:正确安装CUDA是用显卡加速深度学习的

    2024年02月14日
    浏览(32)
  • 3.2.3 存储器与CPU的连接(重难点 看完就会)

    本节内容是存储器中的重点和难点,篇幅较长。并不用担忧,看完这片文章,你会对知识点十分了解,并且会用几道题目来巩固一下内容。 由于CPU所要执行的指令和数据都保存在主存当中,并且执行完成后,需要将执行结果保存回主存。二者之间的联系是非常频繁,所以他们

    2024年02月01日
    浏览(39)
  • C初阶必写的C语言小游戏—扫雷,一看就会,看完就能写

    人尽皆知的扫雷小游戏,原理简单,写法也简单,我会通过C语言分各个部分将这个小游戏进行剖析,一看就会! 我们需要新建一个头文件game.h,两个源文件game.c和text.c,一共三个文件 他们的关系是这样的: test.c是主体,是游戏的测试逻辑 game.c是游戏的实现逻辑 game.h是实现

    2024年02月05日
    浏览(32)
  • Vue2简单使用及相关基础知识概念(适合小白入门,看完就能上手)

    MVC模式(同步通信为主):Model、View、Controller MVP模式(异步通信为主):Model、View、Presenter MVVM模式(异步通信为主):Model、View、ViewModel(目前主要的模式) 2.1 概念 MVVM是一种软件架构设计模式。MVVM的核心是ViewModel层,负责转换Model层中的数据对象来让数据变得更加容易

    2024年02月07日
    浏览(46)
  • 【ChatGPT】GPT实现原理大解析——看完就知道什么叫颠覆

    ChatGPT 能够自动生成类似于人类写作的文本,这一点非常引人注目,也令人意外。但它是如何实现的?为什么它能够如此出色地生成我们认为有意义的文本?我的目的是在这里概述ChatGPT内部的运行情况,并探讨它能够如此出色地产生有意义文本的原因。 首先需要解释的是,

    2023年04月25日
    浏览(35)
  • Java 中反射的概念、作用和特点,在什么情况下使用反射及使用实例

    反射(Reflection)是 Java 的一种特性,它可以让程序在运行时获取自身的信息,并且动态地操作类或对象的属性、方法和构造器等。通过反射功能,可以让我们在不知道具体类名的情况下,依然能够实例化对象,调用方法以及设置属性。 反射的作用有以下几点: 运行时探查类

    2024年02月06日
    浏览(37)
  • 中文编程最高境界,不用编程,会用excel就会用,香不香?

    一直以来,关于中文编程的争议从未消停过。现如今,中文编程发展又是如何? ★为了实现中文编程,从未停下脚步 我们知道,中国人一直以来为了实现中文编程付出了不懈的努力,前前后后研发了几十种中文编程语言。比如我们常见的易语言、习语言、丙正正、O语言等等

    2024年02月05日
    浏览(43)
  • 看完就能懂!ElasticSearch-垃圾回收器优化

    当代主流虚拟机(Hotspot VM)的垃圾回收都采用“分代回收”的算法。“分代回收”是基于这样一个事实:对象的生命周期不同,所以针对不同生命周期的对象可以采取不同的回收方式,以便提高回收效率。 新生代:分三个区:一个Eden区,两个Survivor区,默认内存占比8:1:

    2024年04月15日
    浏览(20)
  • 扫雷游戏【敢看完就敢教会你】------- C语言

    目录 一、扫雷游戏介绍 二、实现游戏的前期工作 1.  游戏的原理逻辑 2.  初始化雷区 三、代码实现游戏 1.  实现 test.c 文件 2.  实现 Mine_Sweeper.c 文件 2.1  雷区初始化函数 2.2  埋地雷函数 2.3  展示雷区函数 2.4  排查地雷函数 2.4.1  排查地雷子函数 2.4.2  标记地雷子函数 2

    2024年02月15日
    浏览(22)
  • Python以及Pycharm保姆级的下载安装教程,看完就懂

    接下来看看由辉辉所写的关于Python的相关操作吧 目录 🥳🥳Welcome Huihui\\\'s Code World ! !🥳🥳 一.Python的安装 1.下载地址 2.下载步骤 二.Pycharm的安装  1.下载地址 2.下载步骤 Python的下载地址 https://www.python.org/ 注意:如果是自己在浏览器搜索的话,尽量选择自带的浏览器(或者自己

    2024年02月14日
    浏览(37)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包