『Java』通过反射(Reflection)访问类属性和调用方法

2021/11/8 17:12:42

本文主要是介绍『Java』通过反射(Reflection)访问类属性和调用方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 前言
    • 获取类
    • 实例化类
  • 一、通过反射访问实例的属性
    • 获取属性
    • 更改属性
  • 二、通过反射调用实例的方法
    • 调用普通方法
    • 调用静态方法
    • ※调用构造方法
  • 三、通过反射获取父类
  • 四、通过反射获取接口

前言

反射(Reflection)能够在代码运行期间、对任意未知类或对象访问属性和调用方法

反射的思想是建立对类的引用、然后通过传入对象名、访问对象的属性或者调用方法,Java机制是对每一个被加载的类新建一个唯一的实例,然后将该实例和类联系在一起

获取类

  • 通过每个实例的getClass()方法
Integer a = 1;
Class cls 1 = a.getClass();

String b = "Hello";
Class cls2 = b.getClass();
  • 通过类的静态属性xxx.class
Class cls1 = String.class;
  • 通过完整类名
Class cls3 = null;
try {
	cls3 = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
	e.printStackTrace();
}

实例化类

普通实例化使用new

int[] ints = new int[1];

使用反射使用Class.newInstance()实例化

String str = String.class.newInstance();

一、通过反射访问实例的属性

由于所有类都继承自Object类,在我们不知道某类的时候,将它new成Object类,而我们无需去探究它的内部究竟是什么、接着我们获取它的类用以建立反射,才用上文提到的方法xxx.getClass()获取

获取属性

属性在field域中,对一个类使用Class.getField(String name)即可获取它的属性,下面的f即是到Person类属性name的反射,然后通过Field.get(String instanceName)方法传入我们实例名称即可获取此实例的name属性

import java.lang.reflect.Field;

public class Main {
    public static void main(String[] args) throws Exception{
        Object obj = new Person("zhangsan");
        
        Class cls = obj.getClass();
        Field f = cls.getField("name");
        Object value = f.get(obj);
        
        System.out.println(value); // zhangsan
    }
}

class Person{
    public String name;

    public Person(String name){
        this.name = name;
    }
}

可以发现在访问实例的属性的过程中:自始至终都没有关注过实例的类名

更改属性

建立好反射后,更改属性只需要使用set方法,传入实例名和修改后的值即可

对于建立private属性的反射:需要使用Class.getDeclaredField(String name)并且设置Field.setAccessible(true)

import java.lang.reflect.Field;

public class Main {
    public static void main(String[] args) throws Exception{
        Person p = new Person("lisi");
        System.out.println(p.getName()); // lisi
        
        Class cls = p.getClass();
        Field f = cls.getDeclaredField("name");
        f.setAccessible(true);
        f.set(p,"wangwu");
        
        System.out.println(p.getName()); // wangwu
    }
}

class Person{
    private String name;

    public Person(String name){
        this.name = name;
    }

    public String getName() {
        return this.name;
    }
}

二、通过反射调用实例的方法

属性存放在Field中,而方法存放在Method中,使用Class.getMethod(String name,Class valueType1,...,Class valueTypeN)即可获取到方法的反射,多个传参就需要多次传入参数的属性

invoke赋值需要类型转换

调用普通方法

拿到反射后,使用Method.invoke()传入实例和参数即可调用

import java.lang.reflect.Method;

public class Main{
    public static void main(String[] args) throws Exception {
        String s = "Hello World!";
        // substring传参是两个int,起始和终止字符的索引值
        Method f = String.class.getMethod("substring", int.class, int.class);
        String t = (String) f.invoke(s,3,7);
        System.out.println(t); // lo W
    }
}

调用静态方法

由于是静态方法,那invoke无需传入参数,即传入null

import java.lang.reflect.Method;

public class ReflectionUseStaticMethod {
    public static void main(String[] args) throws Exception {
        Method m = Integer.class.getMethod("parseInt", String.class);
        Integer n = (Integer) m.invoke(null,"12");
        System.out.println(n); // 12
    }
}

※调用构造方法

之前提到可以用newInstance()实例化,但是它只能调用该类的public无参数构造方法。如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用。那么就需要调用它的构造方法了。

newInstance返回的是Object对象,所以需要向下转型

import java.lang.reflect.Constructor;

public class Main {
    public static void main(String[] args) throws Exception{
        Constructor cs = Integer.class.getConstructor(int.class);
        Integer a = (Integer) cs.newInstance(123);

        System.out.println(a); // 123
    }
}

三、通过反射获取父类

使用方法Class.getSuperclass()能够获取父类

public class ReflectionGetFatherClass {
    public static void main(String[] args) throws Exception {
        Class cls = Integer.class;
        Class father = cls.getSuperclass();
        System.out.println(father); // class java.lang.Number
    }
}

四、通过反射获取接口

使用方法Class.getInterfaces()能够获取接口数组(接口也是类

package LiaoxuefengTest;

public class ReflectionGetInterfaces {
    public static void main(String[] args) throws Exception {
        Class cls = Integer.class;
        Class[] ifs = cls.getInterfaces();
        for (Class i:ifs){
            System.out.println(i); // interface java.lang.Comparable
        }
    }
}

欢迎在评论区留言,欢迎关注我的CSDN @Ho1aAs



这篇关于『Java』通过反射(Reflection)访问类属性和调用方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程