JAVA反射(原理+使用)

news2024/11/20 19:19:30

引言

反射是一种机制,能够使java程序在运行过程中,检查,获取类的基本信息(包,属性,方法等),并且可以操作对象的属性和方法
反射是框架实现的基础

反射的原理

在这里插入图片描述
讲述反射的原理之前,我们先看下java是如何创建对象的

  1. javac将java源文件,编译成 字节码文件(class文件)
  2. JVM 按需加载 字节码文件,将class文件加载为 对应的Class 对象,存放在 堆内存
    (每个class文件只会被加载成一个 Class对象, 因为类只加载一次且类加载是同步机制,只能有一个线程加载这个类)
  3. 根据Class对象 生成 我们熟知的 java对象
    也就是说 平时我们通过new 的方式创建对象就是通过 内存中的Class对象 来创建的。
    而反射是如何创建的呢?可以看下面这张图
    在这里插入图片描述

首先可以确定的是,反射也是通过 Class对象来创建的。因为只有Class对象 有目标对象的详细信息。
与new 一个对象不同的是:
反射在执行之前,不知道自己要创建什么样的类,甚至不知道这个类是否存在,所以说,反射只有在运行到自己时,才能获取Class对象。也只有在运行时,可以检查和使用对应的类信息。

如上图 红色箭头所指,反射是在运行时,根据用户配置的参数(全限定名等)获取对应的Class对象,然后才能创建对象。

那么这样有什么好处呢?

根据反射可以通过类名参数,动态的生成对象,降低了耦合性,可以使程序更加灵活,几乎所有的框架技术都是依赖反射完成的

有什么弊端?

前面说了,反射是在运行时去找自己的Class对象,那么就有一些问题要处理,这个Class对象是否真的存在,或者是否合法等。处理这些问题自然需要时间的,所以反射的性能肯定不如直接new对象

但以现在的硬件水平,这种差距几乎是微乎其微的
new 一个对象 是在 编译期就进行了合法性检查

反射的使用介绍

相关类

java.lang.Class

代表一个类,Class对象表示某个类加载后在堆中的对象
内部含有类的所有信息,是创建的对象的关键
获得方法

// 1. 通过对象类
Class<Cat> cls1 = Cat.class;
Cat cat1 = cls1.newInstance();

// 2. 通过全限定名
Class<?> cls2 = Class.forName("com.wenzhen.interview.basics.reflection.Cat");
Cat cat2 = (Cat) cls2.newInstance();

// 3. 通过对象
Cat cat = new Cat();
Class<? extends Cat> cls3 = cat.getClass();
Cat cat3 = cls3.newInstance();

// 4. 通过类加载器(4种)
ClassLoader classLoader = cat.getClass().getClassLoader();
Class<?> aClass = classLoader.loadClass("com.wenzhen.interview.basics.reflection.Cat");

// 5. 包装类
Class<Integer> type = Integer.TYPE; // 此时获取的是 int.class
Class<Integer> integerClass = Integer.class; // 这个才是真正的包装类的class

java.lang.reflect.Field

代表类的成员变量,Field对象表示某个类的成员变量
使用案例

Class<Cat> cls1 = Cat.class;
Cat cat = cls1.newInstance();//实例化
System.out.println(cat);//Cat(id=null, name=null)
//cls1.getFields() 只能获取public 修饰的属性
Field[] fields = cls1.getDeclaredFields();//获取全部声明的属性
for (Field field : fields) {
    field.setAccessible(true);//设置访问允许,//取消反射在方法调用时安全检查 破坏封装性,可以直接操作私有成员变量,提高性能
    System.out.println(field.getName());//id,name
    field.set(cat,"1");//设置属性值
}
System.out.println(cat);//Cat(id=1, name=1)

java.lang.reflect.Method

代表类的方法,Method对象表示某个类的方法
使用案例

Class<Cat> cls1 = Cat.class;
Cat cat = cls1.newInstance();//实例化
Field name = cls1.getDeclaredField("name");
name.setAccessible(true);
name.set(cat,"五花肉");//设置属性值,猫咪叫 五花肉
//cls1.getMethods() 只能获取public修饰的方法
Method[] declaredMethods = cls1.getDeclaredMethods();//获取全部方法
for (Method method : declaredMethods) {
    if(!"cry".equals(method.getName())){
        //排除非cry的方法
        continue;
    }
    method.setAccessible(true);//设置访问允许
    if(method.getParameterCount() == 0){
        //如果一个参数,执行无参方法
        Object invoke = method.invoke(cat);//五花肉: 喵喵
    }else if(method.getParameterCount() == 1){
        //如果一个参数,执行有参方法,多个参数以此类推
        Object invoke = method.invoke(cat,"hihi");//五花肉: hihi
    }
}

java.lang.reflect.Constructor

代表类的构造方法,Constructor对象表示构造器
使用案例

Class<Cat> cls1 = Cat.class;
Constructor<Cat> constructor = cls1.getConstructor();//无参构造
Cat cat = constructor.newInstance();
System.out.println(cat);//Cat(id=null, name=null)
Constructor<Cat> constructor1 = cls1.getConstructor(String.class);//有参构造(一个参数)
Cat cat1 = constructor1.newInstance("五花肉");
System.out.println(cat1);//Cat(id=null, name=五花肉)

Constructor<Cat> constructor2 = cls1.getConstructor(String.class,String.class);//有参构造(两个参数)
Cat cat2 = constructor2.newInstance("1","五花肉");
System.out.println(cat2);//Cat(id=1, name=五花肉)

常用方法介绍

Class<Cat> cls1 = Cat.class;
//getName:获取全类名
System.out.println(cls1.getName());//com.wenzhen.interview.basics.reflection.Cat
//getSimpleName 获取简单类名
System.out.println(cls1.getSimpleName());//Cat
//getPackage 以Package形式返回 包信息
System.out.println(cls1.getPackage());//package com.wenzhen.interview.basics.reflection
//getSuperClass 以Class形式返回父类信息
Class<?> superclass = cls1.getSuperclass();
System.out.println(superclass);//class com.wenzhen.interview.basics.reflection.Animal
//getInterfaces 以Class[]形式返回接口信息
Class<?>[] interfaces = cls1.getInterfaces();
for (Class<?> anInterface : interfaces) {
    System.out.println(anInterface);//interface com.wenzhen.interview.basics.reflection.Base
}
Annotation[] annotations = cls1.getAnnotations();
for (Annotation annotation : annotations) {
    //注意:Lombok 在编译时生成代码,生成的代码不包括注解信息
    System.out.println(annotation);//注解信息
}

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

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

相关文章

covfefe 靶机/缓冲区溢出

covfefe 信息搜集 存活检测 详细扫描 后台网页扫描 80 端口 31337 端口 网页信息搜集 分别访问扫描出的网页 说有三个不允许看的内容 尝试访问 第一个 flag 访问 .ssh 文件 继续根据提示访问 获取了三个 ssh 文件 ssh 登录 在下载的 id_rsa_pub 公钥文件中发现了…

leetCode 11. 盛最多水的容器 + 双指针

11. 盛最多水的容器 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/container-with-most-water/description/?envTypestudy-plan-v2&envIdtop-interview-150 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是…

【Java基础面试三十三】、接口和抽象类有什么区别?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;接口和抽象类有什么区别…

大同小异!如何在苹果不同类型设备上更改AirDrop的名称

你可以更改你的AirDrop ID&#xff0c;让其他人看到你名字之外的东西。本文介绍了如何在iPhone、iPad和Mac上更改AirDrop名称。 如何在iPhone上更改AirDrop名称 在iPhone上更改AirDrop名称涉及到你可能不想做的更改。幸运的是&#xff0c;这在iPad和Mac上不是真的&#xff0c…

【408数据结构】第一章 绪论

第一章 绪论 1.数据结构基本概念及三要素 一.数据结构基本概念 1.数据 信息的载体&#xff0c;能被客观事物描述的数字&#xff0c;字符以及能被计算机程序识别和处理的符号的集合 2.数据元素 数据的基本单位&#xff0c;一个数据元素可由若干个数据项&#xff08;构成数…

Unity Animation--动画剪辑(创建动画)

创建一个新的动画编辑 创建新的动画剪辑 &#xff0c;在场景中选择一个GameObject&#xff0c;然后打开“ 动画”窗口&#xff08;顶部菜单&#xff1a;&#xff09;“ 窗口” >“ 动画” >“ 动画”。 如果GameObject 中尚未分配任何动画剪辑&#xff0c;“创建”按钮…

pytorch nn.Embedding 读取gensim训练好的词/字向量(有例子)

最近在跑深度学习模型&#xff0c;发现Embedding随机性太强导致模型结果有出入&#xff0c;因此考虑固定初始随机向量&#xff0c;既提前训练好词/字向量&#xff0c;不多说上代码&#xff01;&#xff01; 1、利用gensim训练字向量&#xff08;词向量自行修改&#xff09; #…

YCSB on MySQL(避免重复load)

一、编译安装MySQL 下载mysql5.7.28源码 https://downloads.mysql.com/archives/community/ Select Operating System 选择 Source Code Select OS version 选择 All Operating Systems 选择带有boost的版本 安装系统包 apt -y install make cmake gcc g perl bison libai…

AAOS CarMediaService 服务框架

文章目录 前言MediaSessionCarMediaService作用是什么&#xff1f;提供了哪些接口&#xff1f;如何使用&#xff1f;CarMediaService的实现总结 前言 CarMediaService 是AAOS中统一管理媒体播放控制、信息显示和用户交互等功能的服务。这一服务依赖于android MediaSession框架…

JVM第十五讲:调试排错 - Java 内存分析之堆外内存

调试排错 - Java 内存分析之堆外内存 本文是JVM第十五讲&#xff0c;Java 内存分析之堆外内存调试排错。Java 堆外内存分析相对来说是复杂的&#xff0c;美团技术团队的Spring Boot引起的“堆外内存泄漏”排查及经验总结可以为很多Native Code内存泄漏/占用提供方向性指引。 文…

政企互动 | 雨花台区委统战部一行走访调研聚铭网络

2023年10月19日上午&#xff0c;雨花台区委统战部副部长、台侨办主任勾宏展一行3人到聚铭网络调研走访&#xff0c;聚铭网络总经理唐开达热情接待了来访一行&#xff0c;并详尽地介绍了聚铭网络的发展历程、产品体系、企业文化等相关情况。 在聚铭网络总经理唐开达的陪同下&am…

Mysql表结构差异比较

1、背景 我们在开发过程中&#xff0c;大部分情况下都是好几个版本一起并行&#xff0c;有时候如果某个版本表结构改动较大&#xff0c;但是忘记了记录DDL脚本&#xff0c;这个时候需要人工去把新增或修改的DDL脚本整理出来&#xff08;主要是为了解决 数据库新增字段&#xff…

ArcGIS笔记9_数据源缺少空间参考信息?如何定义坐标系?

本文目录 前言Step 1 确定好要赋予给目标文件的恰当坐标系Step 2 定义坐标系 前言 有时从其他软件转换得到了shp文件&#xff0c;拖到ArcGIS后却出现“未知的空间参考&#xff1a;添加的数据源缺少空间参考信息 不能投影”的提示&#xff0c;如下图所示&#xff1a; 这种情况就…

go-fastdfs安装(国产分布式文件系统)

开源协议&#xff1a; Unlicense官网地址&#xff1a; https://sjqzhang.github.io/go-fastdfs/#vision安装: wget --no-check-certificate https://github.com/sjqzhang/go-fastdfs/releases/download/v1.3.1/fileserver -O fileserver && chmod x fileserver &…

【AIGC核心技术剖析】Hotshot-XL 一种 AI 文本转 GIF 模型(论文 + 代码:经过训练可与Stable Diffusion XL一起使用)

Hotshot-XL 是一种 AI 文本转 GIF 模型,经过训练可与Stable Diffusion XL一起使用。 Hotshot-XL 可以使用任何经过微调的 SDXL 模型生成 GIF。这意味着两件事: 您将能够使用您可能想要使用的任何现有或新微调的 SDXL 模型制作 GIF。 如果您想制作个性化主题的 GIF,您可以…

一张图帮你看懂,在浏览器输入网址回车后,都发生了什么?

首先我们来看图&#xff1a; 当我们在浏览器中输入一个网址&#xff0c;例如&#xff1a;baidu.com&#xff0c;按下回车键后&#xff0c;会发生什么呢&#xff1f; 主要会发生以下这些过程&#xff1a;域名解析&#xff08;获取IP地址&#xff09;、建立HTTP连接、发送HTTP请…

通用音乐播放器蜂鸣器AX301开发板verilog,视频/代码

名称&#xff1a;通用音乐播放器代码&#xff0c;蜂鸣器播放音乐 软件&#xff1a;Quartus 语言&#xff1a;Verilog 代码说明&#xff1a;本代码为音乐播放器通用代码&#xff0c;只需修改管脚即可适配其他开发板 代码功能&#xff1a; 设计一个音乐播放器&#xff0c;使用…

C#面对对象(英雄联盟人物管理系统)增加,查询,删除

目录 英雄信息类 因为要在两个窗体里面调用字典&#xff0c;所以要写一个字典的静态变量 添加功能 查询功能 删除功能 英雄信息类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Windo…

Required MultipartFile parameter ‘file‘ is not present

出现这个原因我们首先想到的是加一个RequestParam("file")&#xff0c;但是还有可能的原因是因为我们的名字有错误 <span class"input-group-addon must">模板上传 </span> <input id"uploadFileUpdate" name"importFileU…

Shell 脚本案例

1.编写hello world脚本 #!/bin/bash ############################################################## # File Name: hello_world.sh # Version: V1.0 # Author: oldchild # Email: 2363543991qq.com # Organization: https://blog.csdn.net/m0_63636799?spm1000.2115.3001.…