介绍
Java程序员都知道,类中private修饰的字段、方法,只能在类内部使用;那真的没有办法在类外部使用private修饰的成员么?这时本篇的主角登场了:反射机制提供在运行时,对于任意一个类,都能够访问这个类的所有信息(构造函数、字段、方法等,也不管是public还是private修饰的)。
在java中,编写的类都是.java结尾,编译后是以.class结尾。程序运行后,.class文件加载到jvm中,转换为Class对象。类可以有多个对象,但这个类对应的Class对象仅有一个。就是通过这个Class对象,来访问类的所有信息。
获取Class对象
有3种方式:
1.类名.class
2.类的实例.getClass()
3.Class.forName(“类的全路径”);
假设项目中,fanshe包下有一个Student类,使用上面的三种方式:
import fanshe.Student;
Class aClass = Student.class;
Student stu = new Student();
Class bClass = stu.getClass();
Class cClass = Class.forName("fanshe.Student");
//都会返回true
System.out.println(aClass == bClass);
System.out.println(bClass == cClass);
常用方法
String aClass.getName();//获取全路径类名
String aClass.getName();//获取类名
Object aClass.newInstance();//调用无参构造函数,得到类的实例
Constructor[] aClass.getConstructors();//获取public修饰的所有构造函数
Constructor aClass.getConstructor(Class...);//获取public修饰的某个构造函数
Constructor[] aClass.getDeclaredConstructors();//获取所有的构造函数,不管哪
种修饰符
Constructor aClass.getDeclaredConstructor(Class...);//获取某个构造函数
constructor.newInstance(实参数值列表);//调用对应的构造函数,得到类的实例
Field[] aClass.getFields();//获取public修饰的所有属性(包括父类)
Field aClass.getField(String name);//获取指定名称的public修饰的某个属性(包括
父类)
Field[] aClass.getDeclaredFields();//获取所有属性,不管哪种修饰符(不包括父类)
Field aClass.getDeclaredField(String name);//获取指定名称的某个属性,不管哪种
修饰符(不包括父类)
Object field.get(实例);//获取相应属性的值
boolean field.isAccessible();//属性是否允许访问
field.setAccessible(true);//使属性允许访问
field.set(实例, 值);//属性赋值
Method[] aClass.getMethods();//获取public修饰的所有方法(包括父类)
Method aClass.getMethod(String name, Class...);//获取某个public的方法(包括
父类)
Method[] aClass.getDeclaredMethods();//获取所有方法,不管哪种修饰符(不包括
父类)
Method aClass.getDeclaredMethod(String name, Class...);//获取某个方法,不管
哪种修饰符(不包括父类)
method.invoke(Object obj, Object...);//调用对应的方法
代码示例
创建实体类
package fanShe;
import lombok.Data;
@Data
public class Father {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 身高
*/
private Integer height;
}
package fanShe;
import lombok.Data;
@Data
public class Son extends Father {
public Son() {
this.score = 60;
}
public Son(int score, String hobby) {
this.score = score;
this.hobby = hobby;
}
/**
* 成绩
*/
private int score;
/**
* 爱好
*/
private String hobby;
public void sayHello() {
System.out.println("成绩:" + score + ",爱好:" + hobby);
}
@Override
public String toString() {
return "Son{\r\n" +
"score=" + this.score + ",\r\n" +
"hobby='" + this.hobby + "'\r\n" +
'}';
}
}
获取构造函数并调用
package fanShe;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test {
public static void main(String[] args) throws ClassNotFoundException,
IllegalAccessException, InstantiationException, NoSuchMethodException
, InvocationTargetException {
Class c = Class.forName("fanShe.Son");
//调用无参的构造函数
Object o = c.newInstance();
System.out.println(o.toString());
//获取第一个参数是int类型、第二个参数是String类型的构造函数
Constructor constructor = c.getDeclaredConstructor(int.class,
String.class);
//调用构造函数并给参数赋值
Object o1 = constructor.newInstance(100, "打篮球");
System.out.println(o1);
}
}
获取属性
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) throws ClassNotFoundException,
IllegalAccessException {
Class c = Class.forName("fanShe.Son");
//取Son类的属性
Field[] fields = c.getDeclaredFields();
for(int i = 0; i < fields.length; i++) {
System.out.println(Modifier.toString(fields[i].getModifiers())
+ "," + fields[i].getName());
}
System.out.println("---");
//取Son类所有的属性
Son son = new Son(90, "学编程");
son.setName("coder");
son.setAge(18);
son.setHeight(183);
List<Field> fieldList = new ArrayList<>();
while (c != null){
Field[] array = c.getDeclaredFields();
fieldList.addAll(Arrays.asList(array));
c = c.getSuperclass();
}
for(Field field : fieldList) {
boolean access = field.isAccessible();
if(!access) {
//不设置,取属性的值是抛异常
field.setAccessible(true);
}
System.out.println(field.getName() + ":" + field.get(son));
field.setAccessible(access);
}
}
}
获取方法并调用
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException {
Class c = Class.forName("fanShe.Son");
Constructor constructor = c.getConstructor(int.class,
String.class);
Object obj = constructor.newInstance(99, "游泳");
Method method = c.getDeclaredMethod("sayHello");
method.invoke(obj);
}
}