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反射机制详解——框架的灵魂所在 的相关文章

  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • Java EE:如何获取我的应用程序的 URL?

    在 Java EE 中 如何动态检索应用程序的完整 URL 例如 如果 URL 是 localhost 8080 myapplication 我想要一个可以简单地将其作为字符串或其他形式返回给我的方法 我正在运行 GlassFish 作为应
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • 列出jshell中所有活动的方法

    是否有任何命令可以打印当前 jshell 会话中所有新创建的方法 类似的东西 list但仅适用于方法 您正在寻找命令 methods all 它会打印所有方法 包括启动 JShell 时添加的方法 以及失败 被覆盖或删除的方法 对于您声明的
  • 路径中 File.separator 和斜杠之间的区别

    使用有什么区别File separator和一个正常的 在 Java 路径字符串中 与双反斜杠相反 平台独立性似乎不是原因 因为两个版本都可以在 Windows 和 Unix 下运行 public class SlashTest Test
  • Java TestNG 与跨多个测试的数据驱动测试

    我正在电子商务平台中测试一系列商店 每个商店都有一系列属性 我正在考虑对其进行自动化测试 是否有可能有一个数据提供者在整个测试套件中提供数据 而不仅仅是 TestNG 中的测试 我尝试不使用 testNG xml 文件作为机制 因为这些属性
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐