『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,name,class,public,实例,Class,String 来源: https://blog.csdn.net/Xxy605/article/details/121207536