在Java中,反射是指在运行时动态地获取和使用类的信息的能力。反射允许程序在运行时检查类、接口、字段和方法,以及动态实例化对象、调用方法和访问或修改字段的属性。简单来说,对于任意一个类,通过反射就可以知道这个类的所有属性和方法,并且可以通过反射进行调用。
类名 | 用途 |
Class类 | 代表类的实体,表示类和接口 |
Field类 | 代表类的属性 |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
方法 | 用途 |
getClassLoader() | 获得类的加载器 |
getDeclaredClasses() | 返回一个数组,数组中包含该类的所有类和接口类的对象 |
forName(String className) | 根据类名返回类的对象 |
newInstance() | 创建类的实例 |
getName() | 获得类的完整路径名,例如 Student.class.getName() |
在反射之前,我们要获得需要反射的类的Class对象,然后通过Class对象的方法,达到反射的目的,例如我们要获取Student类的对象:
class Student{
private String name = "zhangsan";
public int age = 18;
public Student(){
System.out.println("无参数构造方法");
}
private Student(String name, int age){
this.name = name;
this.age = age;
}
private void set(String name, int age){
System.out.println(name + " " + age);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
// Student类的 Class类对象 只有一个,a,b,c的值相同
public static void main(String[] args) {
//1
Class> a;
try {
a = Class.forName("Student");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
//2
Class> b;
b = Student.class;
//3
Student student = new Student();
Class> c = student.getClass();
}
}
上面提到的三种方法只是得到了Student类的class类对象,不是得到Student类的实例化对象,我们要通过得到的Student类的class类对象来实例化一个Student对象。例如:
public class Demo1 {
public static void reflectCreateClass(){
Class> a;
try {
a = Class.forName("Student");
//newInstance()是创建一个a的实例,返回的类型是Object
//所以要向下转型
Student student = (Student) a.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
方法 | 用途 |
getConstructor(Class...> parameterTypes) | 获取该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获取该类的所有公有构造方法 |
getDeclaredConstructor(Class...> parameterTypes) | 获取该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获取该类的所有构造方法 |
注:getConstructor()方法的括号中填写我们需要反射的构造方法参数类型的class类对象,举一个反射私有构造方法的例子,这里的Student类和上文中的一样:
public static void reflectPrivateConstrutor(){
Class> a;
try {
a = Class.forName("Student");
//使用反射得到私有构造方法
Constructor constructor =
(Constructor) a.getDeclaredConstructor(String.class, int.class);
//私有方法不能在类外使用,要想调用,我们要给予权限,也就是下面的代码
constructor.setAccessible(true);
//调用私有的构造方法并传参
Student student1 = constructor.newInstance("ll",20);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
方法 | 用途 |
getField(String name) | 获得类对象的某个公有属性 |
getFields() | 获得类对象的全部公有属性 |
getDeclaredField(String name) | 获得类对象的属性(主要用来获得私有) |
getDeclaredFields() | 获得类对象的全部属性(主要用来获得私有) |
举一个反射类的私有属性的例子,这里的Student类和上文中的一样:
public class Demo1 {
//私有属性
private static void reflectPrivateField(){
Class> a;
try {
a = Class.forName("Student");
Field field = a.getDeclaredField("name");//获得name的属性
field.setAccessible(true);//因为私有...
Student student = (Student) a.newInstance();//实例化对象
field.set(student,"wangwu");//将student对象的name改成wangwu
System.out.println(student);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
方法 | 用途 |
getMethod(String name,Class...> parmeterTypes) | 获得该类公有方法 |
getMethods() | 获得该类所有公有方法 |
getDeclaredMethod(String name,Class...> parmeterTypes) | 获得该类方法 |
getDeclaredMethods() | 获得该类所有方法 |
举一个反射类的私有方法的例子,这里的Student类和上文中的一样:
public class Demo1 {
//私有方法
private static void reflectPrivateMethod(){
Class> a;
try {
a = Class.forName("Student");
//(私有方法名,私有方法的参数类型...)
Method method = a.getDeclaredMethod("set", String.class, int.class);
method.setAccessible(true);//因为私有...
Student student = (Student) a.newInstance();
method.invoke(student,"pppp",10);//调用私有方法 (对象,传参...)
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
优点:
缺点: