Java组件化开发教程,Java反射机制详解(由浅入深

本文详细讲解了Java反射机制,包括如何获取类的字段和方法,以及如何访问和修改私有成员。此外,还强调了反射在Java组件化开发中的应用,并提供了学习资源,包括多线程、算法题、面试题解析等,帮助提升程序员的技能水平。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

}



private String getSonName(){

    return mSonName;

}

}




1\. 获取类的所有变量信息

--------------



/**

  • 通过反射获取类的所有变量

*/

private static void printFields(){

//1.获取并输出类的名称

Class mClass = SonClass.class;

System.out.println("类的名称:" + mClass.getName());



//2.1 获取所有 public 访问权限的变量

// 包括本类声明的和从父类继承的

Field[] fields = mClass.getFields();



//2.2 获取所有本类声明的变量(不问访问权限)

//Field[] fields = mClass.getDeclaredFields();



//3. 遍历变量并输出变量信息

for (Field field :

        fields) {

    //获取访问权限并输出

    int modifiers = field.getModifiers();

    System.out.print(Modifier.toString(modifiers) + " ");

    //输出变量的类型及变量名

    System.out.println(field.getType().getName()

             + " " + field.getName());

}

}




以上代码注释很详细,就不再解释了。需要注意的是注释中 2.1 的 `getFields()` 与 2.2的 `getDeclaredFields()` 之间的区别,下面分别看一下两种情况下的输出。看之前强调一下:  

`SonClass` extends `FatherClass` extends `Object` :



*   调用 `getFields()` 方法,输出 `SonClass` 类以及其所继承的父类( 包括 `FatherClass` 和 `Object`) 的 `public` 方法。注:`Object` 类中没有成员变量,所以没有输出。

    

    ```

    类的名称:obj.SonClass

    public java.lang.String mSonBirthday

    public java.lang.String mFatherName

    public int mFatherAge

    ```

    

*   调用 `getDeclaredFields()` , 输出 `SonClass` 类的所有成员变量,不问访问权限。

    

    ```

    类的名称:obj.SonClass

    private java.lang.String mSonName

    protected int mSonAge

    public java.lang.String mSonBirthday

    ```

    



2\. 获取类的所有方法信息

--------------



/**

  • 通过反射获取类的所有方法

*/

private static void printMethods(){

//1.获取并输出类的名称

Class mClass = SonClass.class;

System.out.println("类的名称:" + mClass.getName());



//2.1 获取所有 public 访问权限的方法

//包括自己声明和从父类继承的

Method[] mMethods = mClass.getMethods();



//2.2 获取所有本类的的方法(不问访问权限)

//Method[] mMethods = mClass.getDeclaredMethods();



//3.遍历所有方法

for (Method method :

        mMethods) {

    //获取并输出方法的访问权限(Modifiers:修饰符)

    int modifiers = method.getModifiers();

    System.out.print(Modifier.toString(modifiers) + " ");

    //获取并输出方法的返回值类型

    Class returnType = method.getReturnType();

    System.out.print(returnType.getName() + " "

            + method.getName() + "( ");

    //获取并输出方法的所有参数

    Parameter[] parameters = method.getParameters();

    for (Parameter parameter:

         parameters) {

        System.out.print(parameter.getType().getName()

                + " " + parameter.getName() + ",");

    }

    //获取并输出方法抛出的异常

    Class[] exceptionTypes = method.getExceptionTypes();

    if (exceptionTypes.length == 0){

        System.out.println(" )");

    }

    else {

        for (Class c : exceptionTypes) {

            System.out.println(" ) throws "

                    + c.getName());

        }

    }

}

}




同获取变量信息一样,需要注意注释中 2.1 与 2.2 的区别,下面看一下打印输出:



*   调用 `getMethods()` 方法  

    获取 `SonClass` 类所有 `public` 访问权限的方法,包括从父类继承的。打印信息中,`printSonMsg()` 方法来自 `SonClass` 类, `printFatherMsg()` 来自 `FatherClass` 类,其余方法来自 Object 类。

    

    ```

    类的名称:obj.SonClass

    public void printSonMsg(  )

    public void printFatherMsg(  )

    public final void wait(  ) throws java.lang.InterruptedException

    public final void wait( long arg0,int arg1, ) throws java.lang.InterruptedException

    public final native void wait( long arg0, ) throws java.lang.InterruptedException

    public boolean equals( java.lang.Object arg0, )

    public java.lang.String toString(  )

    public native int hashCode(  )

    public final native java.lang.Class getClass(  )

    public final native void notify(  )

    public final native void notifyAll(  )

    ```

    

*   调用 `getDeclaredMethods()` 方法

    

    打印信息中,输出的都是 `SonClass` 类的方法,不问访问权限。

    

    ```

    类的名称:obj.SonClass

    private int getSonAge(  )

    private void setSonAge( int arg0, )

    public void printSonMsg(  )

    private void setSonName( java.lang.String arg0, )

    private java.lang.String getSonName(  )

    ```

    



三、访问或操作类的私有变量和方法

================



在上面,我们成功获取了类的变量和方法信息,验证了在运行时 **动态的获取信息** 的观点。那么,仅仅是获取信息吗?我们接着往后看。



都知道,对象是无法访问或操作类的私有变量和方法的,但是,通过反射,我们就可以做到。没错,反射可以做到!下面,让我们一起探讨如何利用反射访问 **类对象的私有方法** 以及修改 **私有变量或常量**。



老规矩,先上测试类。



注:



1.  请注意看测试类中变量和方法的修饰符(访问权限);

2.  测试类仅供测试,不提倡实际开发时这么写 : )



**TestClass.java**



![](https://img-blog.csdnimg.cn/20181109194923645.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxNzAxOTU2,size_16,color_FFFFFF,t_70)



3.1 访问私有方法

----------



以访问 `TestClass` 类中的私有方法 `privateMethod(...)` 为例,方法加参数是为了考虑最全的情况,很贴心有木有?先贴代码,看注释,最后我会重点解释部分代码。



/**

  • 访问对象的私有方法

  • 为简洁代码,在方法上抛出总的异常,实际开发别这样

*/

private static void getPrivateMethod() throws Exception{

//1. 获取 Class 类实例

TestClass testClass = new TestClass();

Class mClass = testClass.getClass();



//2. 获取私有方法

//第一个参数为要获取的私有方法的名称

//第二个为要获取方法的参数的类型,参数为 Class...,没有参数就是null

//方法参数也可这么写 :new Class[]{String.class , int.class}

Method privateMethod =

        mClass.getDeclaredMethod("privateMethod", String.class, int.class);



//3. 开始操作方法

if (privateMethod != null) {

    //获取私有方法的访问权

    //只是获取访问权,并不是修改实际权限

    privateMethod.setAccessible(true);



    //使用 invoke 反射调用私有方法

    //privateMethod 是获取到的私有方法

    //testClass 要操作的对象

    //后面两个参数传实参

    privateMethod.invoke(testClass, "Java Reflect ", 666);

}

}




需要注意的是,第3步中的 `setAccessible(true)` 方法,是获取私有方法的访问权限,如果不加会报异常 **IllegalAccessException**,因为当前方法访问权限是“private”的,如下:



java.lang.IllegalAccessException: Class MainClass can not access a member of class obj.TestClass with modifiers “private”




正常运行后,打印如下,**调用私有方法**成功:



Java Reflect 666




3.2 修改私有变量

----------



以修改 `TestClass` 类中的私有变量 `MSG` 为例,其初始值为 “Original” ,我们要修改为 “Modified”。老规矩,先上代码看注释。



/**

  • 修改对象私有变量的值

  • 为简洁代码,在方法上抛出总的异常

*/

private static void modifyPrivateFiled() throws Exception {

//1. 获取 Class 类实例

TestClass testClass = new TestClass();

Class mClass = testClass.getClass();



//2. 获取私有变量

Field privateField = mClass.getDeclaredField("MSG");



//3. 操作私有变量

if (privateField != null) {

    //获取私有变量的访问权

    privateField.setAccessible(true);



    //修改私有变量,并输出以测试

    System.out.println("Before Modify:MSG = " + testClass.getMsg());



    //调用 set(object , value) 修改变量的值

    //privateField 是获取到的私有变量

    //testClass 要操作的对象

    //"Modified" 为要修改成的值

    privateField.set(testClass, "Modified");

    System.out.println("After Modify:MSG = " + testClass.getMsg());

}

}




此处代码和访问私有方法的逻辑差不多,就不再赘述,从输出信息看出 **修改私有变量** 成功:



Before Modify:MSG = Original

After Modify:MSG = Modified




3.3 修改私有常量

----------



在 3.2 中,我们介绍了如何修改私有 **变量**,现在来说说如何修改私有 **常量**,



### 01\. 真的能修改吗?



常量是指使用 `final` 修饰符修饰的成员属性,与变量的区别就在于有无 `final` 关键字修饰。在说之前,先补充一个知识点。



Java 虚拟机(JVM)在编译 `.java` 文件得到 `.class` 文件时,会优化我们的代码以提升效率。其中一个优化就是:JVM 在编译阶段会把引用常量的代码替换成具体的常量值,如下所示(部分代码)。



编译前的 `.java` 文件:



//注意是 String 类型的值

private final String FINAL_VALUE = “hello”;

if(FINAL_VALUE.equals(“world”)){

//do something

}




编译后得到的 `.class` 文件(当然,编译后是没有注释的):



private final String FINAL_VALUE = “hello”;

//替换为"hello"

if(“hello”.equals(“world”)){

//do something

}




### 最后在出来放一波福利吧!希望可以帮助到大家!

> [**戳此获取免费学习资料**](https://gitee.com/vip204888/java-p7)

千千万万要记得:多刷题!!多刷题!!

之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!

篇幅有限,以下只能截图分享部分的资源!!

(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)

![image](https://img-blog.csdnimg.cn/img_convert/524391390f49058e839b418c1be534e2.png)

(2)刷的算法题(还有左神的算法笔记)

![image](https://img-blog.csdnimg.cn/img_convert/f81baeeb2cbdd0ab8151a80025fa4df0.png)

(3)面经+真题解析+对应的相关笔记(很全面)

![image](https://img-blog.csdnimg.cn/img_convert/d969758c783a73c062e3352f0b3dcf13.png)

(4)视频学习(部分)

> ps:当你觉得学不进或者累了的时候,视频是个不错的选择

![image](https://img-blog.csdnimg.cn/img_convert/bfc6313148b65c8b5546bbdf1a9b740b.png)

其实以上我所分享的所有东西,有需要的话我这边可以免费分享给大家,但请一定记住获取方式:[点击这里前往免费获取](https://gitee.com/vip204888/java-p7)

ng

}

最后在出来放一波福利吧!希望可以帮助到大家!

戳此获取免费学习资料

千千万万要记得:多刷题!!多刷题!!

之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!

篇幅有限,以下只能截图分享部分的资源!!

(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)

[外链图片转存中…(img-aD0k9q2M-1628289330545)]

(2)刷的算法题(还有左神的算法笔记)

[外链图片转存中…(img-ouYqi8Q4-1628289330547)]

(3)面经+真题解析+对应的相关笔记(很全面)

[外链图片转存中…(img-4xKDxi29-1628289330548)]

(4)视频学习(部分)

ps:当你觉得学不进或者累了的时候,视频是个不错的选择

[外链图片转存中…(img-CCtMfXp5-1628289330550)]

其实以上我所分享的所有东西,有需要的话我这边可以免费分享给大家,但请一定记住获取方式:点击这里前往免费获取

在这里,最后只一句话:祝大家offer拿到手软!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值