Java 利用反射类操作其他类

素颜马尾好姑娘i 2022-05-31 03:06 392阅读 0赞
反射的概念:

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)

Class反射类一直是Java中较为重要的一部分,说深入了解不敢说,基础的操作其他类的公有属性/方法,私有的属性/方法做个操作,什么是反射类,请参考其他更为详细的文章。

首先创建一个类,Student类:

  1. public class Student {
  2. private String name;
  3. private String sex;
  4. private int age;
  5. public String getName() {
  6. return name;
  7. }
  8. public void setName(String name) {
  9. this.name = name;
  10. }
  11. public String getSex() {
  12. return sex;
  13. }
  14. public void setSex(String sex) {
  15. this.sex = sex;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. public void run(){
  24. System.out.println("奔跑");
  25. }
  26. private String say(String str){
  27. return "他说"+str;
  28. }
  29. @Override
  30. public String toString() {
  31. return "Student{" +
  32. "name='" + name + '\'' +
  33. ", sex='" + sex + '\'' +
  34. ", age=" + age +
  35. '}';
  36. }
  37. }

在这个类中,有三个私有的属性,一个无返回值无参的方法,一个有返回值有参的方法,现在要利用Class反射类要做一个操作,获取这个Student类中的属性并赋值,调用这个类的方法

介绍一下获取Class对象的三种方式:

1、 Object ——> getClass();(封装时常用)
2、 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
3、 通过Class类的静态方法:forName(String className)(常用)

第一种:

  1. Student student = new Student();//这一new 产生一个Student对象,一个Class对象。
  2. Class cls = student.getClass();//获取Class对象

第二种:

  1. Class sls = Student.class;

第三种:

  1. Class sls = Class.forName("com.uhope.uip.item.constants.Student");

第三种就是类所在包的完整路径

三种写法,看自己的需求来写,我这里要介绍的是第一种,因为我对这个反射类进行了一次的封装,封装成工具类方便调用。

创建好了Student类以后,创建一个测试类来进行测试一下看看效果:

在不知道类名的情况下,不把代码写死,想要写的灵活点,那就让使用这个工具类的人自己传一个类进来,那方法中的参数就放一个Object,Object是所有类的父类,所以都是没问题的:

  1. public static void ClassUtil(Object obj){
  2. Class cls = obj.getClass();
  3. }

这样就获取到了别人传入的类

接着要操作类的方法,使用Method:

  1. public static void ClassUtil(Object obj){
  2. try {
  3. Class cls = obj.getClass();
  4. Method method = cls.getMethod("setName",String.class);
  5. method.invoke(obj,"测试名称");
  6. System.out.println(obj);
  7. } catch (NoSuchMethodException e) {
  8. e.printStackTrace();
  9. } catch (IllegalAccessException e) {
  10. e.printStackTrace();
  11. } catch (InvocationTargetException e) {
  12. e.printStackTrace();
  13. }
  14. }

这是操作公有方法的写法,接下来是操作私有方法的写法:

  1. public static void ClassUtil(Object obj){
  2. try {
  3. Class cls = obj.getClass();
  4. Method method = cls.getDeclaredMethod("say",String.class);
  5. method.setAccessible(true);
  6. method.invoke(obj, "哈喽");
  7. } catch (NoSuchMethodException e) {
  8. e.printStackTrace();
  9. } catch (IllegalAccessException e) {
  10. e.printStackTrace();
  11. } catch (InvocationTargetException e) {
  12. e.printStackTrace();
  13. }
  14. }

say是private封装的方法,setName是公有方法,操作私有的,需要 setAccessible(true) 来解除私有状态,还有一个不一样的是需要getDeclaredMethod而不是getMethod方法了,getDeclaredMethod是为了私有方法准备的,由于say是有返回值的方法,这里就不需要System.out.println了,在打印中就会展示出来

SouthEast

接下来是操作Student类中的run方法,run是一个无返回值无参的方法,但是里面写好了内容,这样的话只需要如下代码:

  1. public static void ClassUtil(Object obj){
  2. try {
  3. Class cls = obj.getClass();
  4. Method method = cls.getMethod("run");
  5. method.invoke(obj);
  6. } catch (NoSuchMethodException e) {
  7. e.printStackTrace();
  8. } catch (IllegalAccessException e) {
  9. e.printStackTrace();
  10. } catch (InvocationTargetException e) {
  11. e.printStackTrace();
  12. }
  13. }

三种操作方法的演示好了,需要注意的就是 getDeclaredMethod和getMethod方法的使用区别,以及有无参数的区别,有参数的话要多写两个地方,一个是Method的第二个参数类型,一个是invoke的第二个指定的值。

接下来看调用私有的属性(一般项目中都是私有封装的,所以就讲解一下私有操作),调用方法是Method,调用属性是用Field:

  1. public static void ClassUtil(Object obj){
  2. try {
  3. Class cls = obj.getClass();
  4. Field field = cls.getDeclaredField("name");
  5. field.setAccessible(true);
  6. field.set(obj,"测试名称");
  7. System.out.println(field.get(obj));
  8. }catch (IllegalAccessException e) {
  9. e.printStackTrace();
  10. }catch (NoSuchFieldException e) {
  11. e.printStackTrace();
  12. }
  13. }

和获取私有方法相同,都有一个getDeclared,也需要解除私有状态,通过Field中的set方法,将要给与的值赋进去,查看有没有赋值成功,就用Field的get方法即可,也可以通过Method获取setName方法,将参数写进去,再用Field获取值:

  1. public static void ClassUtil(Object obj){
  2. try {
  3. Class cls = obj.getClass();
  4. Method method = cls.getMethod("setName",String.class);
  5. method.invoke(obj,"Method测试名称");
  6. Field field = cls.getDeclaredField("name");
  7. field.setAccessible(true);
  8. System.out.println(field.get(obj));
  9. } catch (NoSuchFieldException e) {
  10. e.printStackTrace();
  11. } catch (IllegalAccessException e) {
  12. e.printStackTrace();
  13. } catch (NoSuchMethodException e) {
  14. e.printStackTrace();
  15. } catch (InvocationTargetException e) {
  16. e.printStackTrace();
  17. }
  18. }

发表评论

表情:
评论列表 (有 0 条评论,392人围观)

还没有评论,来说两句吧...

相关阅读

    相关 利用Java反射API进行操作

    反射是Java提供的一种能力,它允许程序在运行时检查类、接口、字段和方法信息,并且可以动态地调用这些方法。 以下是一些使用反射API进行类操作的例子: 1. 获取类的信息: