Java进阶:反射(下)

Method类

概述

Method类集成了方法的全部信息(返回值类型、方法全名、参数列表、修饰符等)和对方法的一些操作,利用反射机制和字节码对象,我们可以将一个类中的所有成员函数抽象为Method类,每一个方法都是Method对象

应用

1. 获取一个类中成员函数的全部信息

2. 在Class类中可以获取一个类中的任意函数,无视访问权限限制

3. 在集合中可无视泛型加入其它类型的元素

4. 无视访问权限调用方法

方法

1. void setAccessible(boolean flag) 如果参数为true就暴力解除访问权限锁

2. Object invoke(Object obj, Object ... args)

参数1:调用这个方法的对象,对于静态方法参数1传入null即可

参数2:调用方法时要传递的参数列表,对于无参方法,则无参数2

返回值:方法的返回值,对于void类型返回null,对于基数类型则返回对应的包装类类型的对象

Class类中与之相关的方法

1. Method getMethod(String name, Class ... args) 按参数1中的函数名和参数2中的各个参数类型来获取类中与之匹配且公共的成员函数

2. Method getMethods() 一次性获取类中所有公共的成员函数

3. Method getDeclaredMethod(String name, Class ... args) 与第一个方法作用一致,但获取的是类中任意访问权限的成员函数

4. Method[] getDeclaredMethods() 一次性获取类中所有成员函数,无视访问权限限制

package com.reno.d0822;
//Work02.Java
import java.lang.reflect.Method;
import java.util.ArrayList;
/*需求:ArrayList<Integer>的一个对象,在这个集合中添加一个字符串数据,如何实现呢?*/

public class Work02 {
    public static void main(String[] args) throws Exception {
        ArrayList<Integer> li = new ArrayList<>();
        li.add(10);
        li.add(20);
        li.add(30);
        // li.add("HUAWEI P40") 不能通过编译,因为加入的不是Integer类的
        Class<? extends ArrayList> aClass = li.getClass();
        Method method = aClass.getDeclaredMethod("add", Object.class);
        method.invoke(li, "HUAWEI P40");
        for (Object o : li) {
            System.out.println(o);
        }
    }
}

Field类

概述

Field类集成了类的成员变量的所有信息(数据类型、变量全名、访问权限等),在反射中,每个成员变量都看作是一个Field对象

应用

1. 获取成员变量的信息

2. 在Class类中获取类中任意的成员变量,无视访问权限

3. 无视访问权限访问或修改成员变量

方法

1. void setAccessible(boolean flag) 如果参数为true就暴力解除私有成员变量的访问权限锁

2. 

void set(Object obj, Object value) 
void setInt(Object obj, int i)     
void setLong(Object obj, long l)
void setBoolean(Object obj, boolean z) 
void setDouble(Object obj, double d) 

Object get(Object obj)  
int getInt(Object obj) 
long getLong(Object obj) 
boolean getBoolean(Object ob)
double getDouble(Object obj) 

类似于封装中的getter和setter,可以获取或修改成员变量

3. Class getType() 获取成员变量的类型

Notice:如果要用反射获取或修改私有属性值则必须事先用setAccessible(true)暴力破解访问权限锁才可以

Class类中与之相关的方法

1. Field getField(String name) 按照传入的名字获取类中公共的成员变量

2. Field[] getFields() 一次性获取类中所有公共成员变量

3. Field getDeclaredField(String name) 按照传入的名字获取类中的成员变量,无视访问权限

4. Field[] getDeclaredFields() 一次性获取类中所有成员变量,无视访问权限限制

package com.reno.d0822;
//PrivateTest.java
public class PrivateTest {
    private String name = "hellokitty";

    public String getName() {
        return name;
    }

}
package com.reno.d0822;
//Work01.java
import java.lang.reflect.Field;
public class Work01 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        PrivateTest test = new PrivateTest();
        System.out.println("Before: " + test.getName()); //为验证程序正确性,先把修改前的私有属性打印出来
        Class<? extends PrivateTest> aClass = test.getClass();//获取字节码对象
        Field nameField = aClass.getDeclaredField("name");//无视访问权限获取私有属性
        nameField.setAccessible(true);//暴力破解私有属性的访问权限
        nameField.set(test, "I'm a Kitty");//修改指定对象属性值
        System.out.println("After: " + test.getName());//将修改后的属性值打印
    }
}

 总结与补充

1. 针对idea里面不能用Alt + Enter快速完成赋值语句的情况,这是因为编码不够规范,把赋值语句写到了代码块或函数体外,正确做法是在类体中定义变量,要在函数体或代码块内写赋值语句或循环/选择语句,idea才能正确给出建议

2. 对于反射可以无视泛型,实际上是泛型只是编译时的"保安",而反射是在运行时通过字节码对类的成员进行操作,泛型当然对反射无效了

3. 对于暴力破解,实际上只是在通过Class类中定义的getDeclaredXXX()获取成员时能做到直接无视访问权限限制,而使用成员类中的getter等方法来操控私有成员时则需先用setAccessible(true)解开访问权限锁才能去操控

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值