Java反射机制详解——框架的灵魂所在

2023-11-02


反射作为框架的核心,在Java中处于一个极为重要的地位,而且反射在Java中属于比较高级的技术,需要有对Java一定的理解才可以掌握好。反射可以在程序运行过程中修改程序的行为。但是与此同时反射也是极其危险的,需要谨慎使用。
Class
Class不同于创建类的关键字class,Class本质上也是一个类,Class对象用来表示为在虚拟机上运行的类和接口。

Class的获取
在反射当中获取Class的方法有三种

通过Object.getClass()
通过类名.class
通过Class.forName(“类的全限定类名”)
Class的名字
Class.getName()

当Class代表一个引用时:其返回全限定类名:“com.clander.MyClander”
当Class代表一个基本数据类型时:其返回它本身。例如:int.class int
当Class代表是数组时:返回[[[I这样类型的名字,例如:int [] 的名字为[I
 

 

String[].getClass().getName() = [L java.lang.String

Class.getSimpleName()
simpleName用于获取内部类的简单类名

当获取类数组的SimpleName时不是在前面加[,而是在后面加[]。

Class.getCanonicalName()
getCanonicalName() 返回的也是全限定类名,但是对于内部类不用$,而用.
getCanonicalName() 对于数组类型同simpleName一样,也是在后面加[]
getCanonicalName() 不同与simpleName的是,不存在的时候返回null,而不是空字符串。
局部类和匿名内部类不存在CanonicalNameClass获取修饰符
获取修饰符
我们可以通过Class.getModifiers();来获取修饰符的值它打印出来是一个数字的形式;我们还可以使用Modifier 类内置的toString() 方法,来将修饰符打印出来。

获取Class的成员
获取Field
Class.getField(String name) 获取的是非私有属性,并且当在当前Class中找不到时会向祖先类获取。
Class.getDeclaredField(String name) 获取的是Class中呗private修饰的属性。
Field[] getDeclaredFields() 获取自身所有的属性但不包含从父类继承下来的属性。
Field[] getFields() 获取自身所有public属性,包括从父类继承下来的。
获取Method
Class.getMethod(String name,Class<?>…parameterTypes) 获取的是非私有方法,并且当在当前Class中找不到时会向祖先类获取。

Class.getDeclaredMethod(String name,Class<?>…parameterTypes) 获取的是Class中呗private修饰的方法。

Method[] getDeclaredMethods() 获取自身所有的方法但不包含从父类继承下来的方法。

Method[] getMethods() 获取自身所有public方法,包括从父类继承下来的。

获取Constructor构造器
与Method和Field基本一致这里不再赘述

Field
Field类型获取
Type getGenericType() 可以返回泛型的类型
Class<?> getType() 返回类型与Class.getName()返回基本相同
获取修饰符
与Class获取修饰符方法一致。

Field的读取和赋值
读取:

Object get(Object o)
byte getByte(Object o)
int getInt(Object o)
long getLong(Object o)
float getFloat(Object o)
double getDouble(Object o)
boolean getBoolean(Object o)
char getChar(Object o)
赋值:

void set(Object o,Object value)
void setByte(Object o,byte value)
void setInt(Object o,int value)
void setLong(Object o,long value)
void setFloat(Object o,float value)
void setDouble(Object o,double value)
void setBoolean(Object o,boolean value)
void setChar(Object o,char value)
Method
获取方法名
**Method.getName()**放回方法名

获取方法参数
Class<?>[] getParameterTypes() 获取所有的参数类型

Type[] getGenericParameterTypes() 获取所有的参数类型包括泛型

获取返回值类型
**Class<?> getReturnType()**获取返回值类型

**Type getGenericReturnType()**获取返回值类型包括泛型

方法的执行(重点!!!)
**public Object invoke(Object obj,Object…args)**invoke方法中的第一个参数表示方法所属类的实例对象,如果这个方法属于静态方法那么这个值为null,后面的可变参数列表为对应参数,返回值为Object。

如果在Method被invoke的过程中本身抛出了异常那么这个异常会被包装在InvocationTargetException中,而通过**InvocationTargetException.getCause()**可以获取真正的异常。在一个private方法被执行之前一定要提前setAccessible(true)

Constructor
Constructor表示为构造方法,主要用于创建类对象。它的方法大体与Method一致,主要重要的方法为创建类对象的方法newInstance()

实验
使用反射解析某个你创建的类,把类中所有的属性、方法、接口都提取出来。要求:通过三种不同的方式获取 Class 对象;
修改解析出来的类的属性值,然后再给类添加新的属性;
调用类方法(包括私有方法、静态方法和构造方法),执行后打印结果;
解析出该类的父类对象,并同样修改其父类的属性值并调用父类的方法。
 

package T08reflection;

/**
 * @Author: Administrator
 * Date: 2021/12/10 15:41
 * @Version:
 * @Description:
 */
public interface Impl {
    void showMe();

}

package T08reflection;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Administrator
 * Date: 2021/12/10 15:33
 * @Version:
 * @Description:
 */
public class A implements Impl {
    public int a = 10;
    private List<String> list = new ArrayList<>();

    public A() {
    }

    public A(int a) {
        this.a = a;
    }

    private void hello() {
        System.out.println("hello");
    }

    private static void a() {
        System.out.println("A!");
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    @Override
    public void showMe() {
        System.out.println("showMe");
    }
}

package T08reflection;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @Author: Administrator
 * Date: 2021/12/10 15:59
 * @Version:
 * @Description:
 */
public class Exemple {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        A a = new A();
        Class<? extends A> aClass = a.getClass();
        Class<A> aClass1 = A.class;
        Class<?> aClass2 = Class.forName("T08reflection.A");
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field.getName());
            System.out.println(Modifier.toString(field.getModifiers()));
            System.out.println("--------------------");
        }
        Field a1 = aClass1.getField("a");
        int a2 = a1.getInt(a);
        System.out.println(a2);
        a1.set(a, 15);
        a2 = a1.getInt(a);
        System.out.println(a2);
        System.out.println("-----------------------------------");
        Method[] declaredMethods = aClass2.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method.getName());
            System.out.println(Modifier.toString(method.getModifiers()));
            System.out.println("----------------------------");
        }
        Method hello = aClass2.getDeclaredMethod("hello");
        hello.setAccessible(true);
        hello.invoke(a);
        Method a3 = aClass.getDeclaredMethod("a");
        a3.setAccessible(true);
        a3.invoke(null);
        Class<?>[] interfaces = aClass1.getInterfaces();
        for (Class<?> tClass:interfaces){
            System.out.println(tClass.getName());
        }

    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java反射机制详解——框架的灵魂所在 的相关文章

  • 使用缩略图器,我可以制作具有相同高度和宽度的缩略图,无论图像大小如何

    In 缩略图器 http code google com p thumbnailator 我正在制作缩略图 如果图像大小是 400 300 并且如果我执行以下操作 Thumbnails of new File original jpg si
  • 如何实现 Eclipse 清理和构建(又名重建)?

    我删除了我的 binEclipse Indigo 中的文件夹 与 Helios 非常相似 现在我想知道如何重建我的 Java 项目 我只是找不到像 Netbeans 中那样的按钮 对于 Eclipse 您可以在下面找到重建选项项目 gt 清
  • 从插件设置 Maven 属性

    我在这里阅读了一些关于如何从 Maven 插件设置属性的问题 其中大多数讨论了应用程序的版本号 似乎没有简单的方法可以做到这一点 我发现的最佳解决方案是拥有一个从插件更新的 filter properties 文件 并由主 pom 文件使用
  • 确定列表编号是否连续

    我在 Java 工作 我有一个无序列表 包含 5 个数字 范围从 0 100 没有重复 我想检测其中 3 个数字是否连续且没有间隙 例子 9 12 13 11 10 true 17 1 2 3 5 true 19 22 23 27 55 f
  • java.io.IOException: EnsureRemaining: 仅剩余 0 个字节,尝试读取 1

    我在 giraph 中的自定义类方面遇到一些问题 我制作了 VertexInput 和 Output 格式 但总是收到以下错误 java io IOException ensureRemaining Only bytes remaining
  • 使用 Bouncy Castle 重建 ED25519 按键 (Java)

    Bouncy Castle 的最新 测试版 版本 bcprov jdk15on 161b20 jar 支持 ED25519 和 ED448 EC 加密以进行签名 我设置了这个完整的工作示例 它按预期工作 我的问题 我是否正确重建了私钥和公钥
  • Java Sound可以用来控制系统音量吗?

    Java 声音优惠FloatControl各种声音线路功能的实例 以及MASTER GAIN http docs oracle com javase 7 docs api javax sound sampled FloatControl T
  • Spring Security登录返回404

    我目前正在使用 Spring 框架开发我的博客 我正在实现 Spring Security 用于登录目的 一切都按预期进行 直到我提交始终返回 404 代码的登录凭据 这是我的 web xml 代码e
  • 如何使用 Tomcat 启用浏览器缓存静态内容(图像、css、js)?

    如何使用 Tomcat 启用浏览器缓存静态内容 图像 css js 首选的解决方案是编辑 spring MVC 配置文件或 web xml 尝试 改变值
  • 使用枚举变量切换字符串

    我有一个具有不同值的枚举 并且想要切换字符串变量 现在 我在尝试将枚举值转换为字符串 可以用作大小写常量 时遇到了困难 我最好的尝试是将枚举转换为字符串数组 但开关似乎不接受数组值作为大小写常量 IntelliJ 说 需要恒定的表达 Enu
  • 无法在android中使用retrofit发出@Post请求

    我正在学习如何在 android 中使用改造 但是每当我尝试从互联网检索数据时 我的应用程序不会返回任何内容我的响应没有成功 我不知道如何修复当前我正在尝试发布的错误并使用此 URL 检索数据https jsonplaceholder ty
  • 公共领域有哪些替代方案?

    我正在用 java 编写一个游戏 正如问题标题建议的那样 我在类中使用公共字段 暂且 据我所知 公共领域很糟糕 我有一些理解其中的原因 但如果有人能澄清为什么你不应该使用它们 那将不胜感激 问题是 从我所看到的来看 这似乎是合乎逻辑的 是使
  • 使用 java 中的准备好的语句插入自定义 SQL 类型

    我有一些自定义类型 它们基本上都是枚举 以下是它们的外观示例 CREATE TYPE card suit AS ENUM spades clubs hearts diamonds 我在 Java 中有一些准备好的语句 看起来像这样 Setu
  • Spring 非托管 bean 的依赖注入

    我有一个非托管的 JPA 域类 它是通过实例化的new操作员 UserAccount account new UserAccount userRepository save account In my UserAccount类 我有一个be
  • 在JAVA中将数据写入.txt文件?

    我想知道是否是在JAVA中将计算的数据写入文本文件 我的 JAVA 代码是一个基于 GUI 的 gpa 计算器 我只想添加一个 JButton 和 ActionListener 它将类名 GPA 点和计算出的 GPA 写入 txt 文件 这
  • 使用 Spark SQL 时找不到 Spark Logging 类

    我正在尝试用 Java 进行简单的 Spark SQL 编程 在程序中 我从 Cassandra 表获取数据 将RDD into a Dataset并显示数据 当我运行spark submit命令 我收到错误 java lang Class
  • 从 Brixton.RC1 开始的 ZuulProxy 未传递授权标头

    从 Spring Cloud 切换时Brixton M5 to Brixton RC1我的 ZuulProxy 不再通过Authorization标头下游到我的代理服务 我的设置中有各种各样的角色 但大多数都相当简单 Authorizati
  • 如何组织课程、课程包[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 您如何决定包名称应该是什么以及什么类应该放入哪个包中 我正在开发一个项目 在该项目中 我不断添加 删除类 并且不确定我是否需要一个新包 或者应该将其添
  • JAVAFX 缩放、ScrollPane 滚动

    I have JAVAFX application with zoom and scale as described here Scale at pivot point in an already scaled node https sta
  • 在Java中将32bpp图像转换为16bpp图像

    如何使用 Java 库将 32bpp 图像 ARGB 转换为 16bpp 图像 ARGB 出于我的好奇 在像素级别 这种转换有什么作用 如果我有一个保存像素值 包含所有通道 的 int 值 那么在转换发生后该 int 会有什么不同 32 位

随机推荐