1. java的反射机制:
Java 中每个类都有 Class 自描述类(描述当前对象类自己的一个类,通过该类实例可以获得类的属性和方法,包括私有属性和构造方法)。
2. 如何获得类中的 Class 对象
(1) 获得 Class 对象的方法:Object 有一个方法, getClass()
static void getClass1(){
Person per = new Person();
Class cls = per.getClass();
System.out.println(cls.getName());
}
(2) 获得 Class 对象的方法:通过 .class 属性
static void getClass2(){
Class cls = Person.class;
System.out.println(cls.getName());
}
(3) 获得 Class 对象的方法:Class 里面有一个静态方法 Class.forName("") 类全名(包名+类名)
static void getClass3(){
try {
Class cls = Class.forName("com.geek99.code_17_01.Person");
System.out.println(cls.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
3. 构造方法反射
// 定义一个 Person 类,有两个构建方法
class Person{
private int pid;
private String name;
private int age;
private Person(){
System.out.println("Person1");
}
public Person(int pid,String name,int age){
this.name = name;
this.age = age;
this.pid = pid;
System.out.println("Person2");
}
}
// 获得无参数的构造方法
static void printConstructor(Class cls){
try {
Constructor c1 = cls.getConstructor(null);
System.out.println(c1);
c1.newInstance(null);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获得有参数的构造方法
static void printConstructor(Class cls){
try {
Constructor c1 = cls.getConstructor(int.class,String.class,int.class);
System.out.println(c1);
c1.newInstance(1,"tom",20);
} catch (Exception e) {
e.printStackTrace();
}
}
4. 获得类中的所有字段的反射
(1) getDeclaredField() 方法可以获得类中的所有字段的反射
// 新建一个 Demo 类
class Demo{
private int test1;
public String test2;
protected boolean test3;
}
// 通过 getDeclaredFields() 方法获得类中的所以字段
static void test1(Class cls){
Field[] fields = cls.getDeclaredFields();
for(Field f: fields){
System.out.print("修饰符:");
System.out.println(Modifier.toString(f.getModifiers()));
System.out.print("类型:");
System.out.println(f.getType());
System.out.print("名称:");
System.out.println(f.getName());
}
}
(2) getDeclaredField() 方法获得对象后进行赋值和取值操作
// 新建一个 Demo 类
class Demo{
private int test1;
public String test2;
protected boolean test3;
}
private static void test2(Class cls) {
try {
// 获得 Demo 类中的 test1 属性(私有的),将赋给 f1
Field f1 = cls.getDeclaredField("test1");
// setAccessible(true) 使得私有属性可以访问
f1.setAccessible(true);
// 创建一个 obj
Object obj = cls.newInstance();
// 将 obj 和 值 100 设置到 f1 中
f1.set(obj, 100);
// 获得 f1 的 obj 并打印
System.out.println(f1.get(obj));
} catch (Exception e) {
e.printStackTrace();
}
}
4. 获得类中的所有方法的反射
(1) 通过 getDeclaredMethods() 方法获得类中的所有方法的反射
// 定义一个 Demo 类
class Demo{
private void test1(){
System.out.println("test1");
}
public void test2(int a){
System.out.println("test2:"+a);
}
public void test3(int a,String b){
System.out.println("test3:"+a+","+b);
}
}
// 通过 getDeclaredMethods() 方法获得类中的方法
static void printMethod(Class cls){
Method[] ms = cls.getDeclaredMethods();
for(Method m:ms){
System.out.print("修饰符:");
System.out.println(Modifier.toString(m.getModifiers()));
System.out.print("名称:");
System.out.println(m.getName());
Parameter[] ps = m.getParameters();
for(Parameter p:ps){
System.out.println(p);
}
}
}
(2) 通过 getDeclaredMethod() 方法获得类中的方法并用 invoke() 调用
// 定义一个 Demo 类,有带参数和不带参数的方法
class Demo{
private void test1(){
System.out.println("test1");
}
public void test2(int a){
System.out.println("test2:"+a);
}
public void test3(int a,String b){
System.out.println("test3:"+a+","+b);
}
}
static void testInvoke(Class cls){
try {
// 通过 getDeclaredMethod() 方法获得不带参数的 test1() 方法,传入 null 参数
Method m1 = cls.getDeclaredMethod("test1", null);
// 设置调用权限
m1.setAccessible(true);
// 通过 invoke() 调用此方法
m1.invoke(cls.newInstance(), null);
// 获得有参数的 test3() 方法
Method m3 = cls.getDeclaredMethod("test3", int.class,String.class);
// 通过 invoke() 调用
m3.invoke(cls.newInstance(), 100,"Hello");
} catch (Exception e) {
e.printStackTrace();
}
}