在运行状态中,对任意一个类,都能知道这个类的所有属性和方法,对任意一个对象,都能调用它的任意一个方法和属性。这种能动态获取信息及动态调用对象方法的功能称为java语言的反射机制
从Oracle的官方文档来看,反射主要应用在以下几方面:
反射的实现原理是什么呢?
反射API | 用途 |
---|---|
Field类 | 提供有关类的属性信息,以及对它的动态访问权限。它是一个封装反射类的属性的类 |
Constructor类 | 提供有关类的构造方法的信息,以及对它的动态访问权限。它是一个封装反射类的构造方法的类 |
Method类 | 提供有关类的方法的信息,包括抽象方法。它是用来封装反射类方法的一个类 |
Class类 | 表示正在运行的Java应用程序中的类的实例 |
Object类 | Object是所有Java类的父类。所有对象都默认实现了Object类的方法 |
package Reflect;
public class User {
private int id;
public String name;
public User(int id,String name){
this.id = id;
this.name = name;
}
public int add(int number){
this.id += number;
return id;
}
}
1、获取class对象
package Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class reflect {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
//获取class对象
//1、通过完整路径名获取class对象
Class clazz = Class.forName("Reflect.User");
//2、通过类的class属性获取
Class clazz1 = User.class;
//3、通过对象来获取,这种方式已经获取了对象不需要再使用反射
User zhangsan = new User(1,"yangguang");
Class clazz2 = zhangsan.getClass();
}
}
2、通过反射来访问成员变量和私有成员变量
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class reflect {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
//获取class对象
//1、通过完整路径名获取class对象
Class clazz = Class.forName("Reflect.User");
//2、通过类的class属性获取
Class clazz1 = User.class;
//3、通过对象来获取,这种方式已经获取了对象不需要再使用反射
User zhangsan = new User(1,"yangguang");
Class clazz2 = zhangsan.getClass();
//通过反射来访问成员变量,name是public的
Field idfield = clazz.getField("name");
System.out.println(idfield.get(zhangsan));
//这时候可能有人会说,已经通过zhangsan创建了对象,直接用System.out.println(zhangsan.name);不就可以把成员变量打印出来,为什么要多此一举用反射?
//其实通过反射还可以访问类的私有成员变量,通过getDeclareField方法
Field field = clazz.getDeclaredField("id");
field.setAccessible(true);
System.out.println(field.get(zhangsan));
}
}
3、通过反射来调用方法
package Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class reflect {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
//获取class对象
//1、通过完整路径名获取class对象
Class clazz = Class.forName("Reflect.User");
//2、通过类的class属性获取
Class clazz1 = User.class;
//3、通过对象来获取,这种方式已经获取了对象不需要再使用反射
User zhangsan = new User(1,"杨广");
Class clazz2 = zhangsan.getClass();
//通过反射来调用方法,如果是私有方法用getDeclareMethod
Method method = clazz.getMethod("add",int.class);
System.out.println(method.invoke(zhangsan,100));
}
}
4、获取构造方法,创建实例
package Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class reflect {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException, InstantiationException {
//获取class对象
//1、通过完整路径名获取class对象
Class clazz = Class.forName("Reflect.User");
//2、通过类的class属性获取
Class clazz1 = User.class;
//获取构造方法,传入构造方法的两个参数类型,若是私有构造方法,则用getDeclareConstructor
Constructor constructor = clazz.getConstructor(int.class,String.class);
//创建实例
Object zhangsan = constructor.newInstance(1,"杨坚");
Field field = clazz.getField("name");
System.out.println(field.get(zhangsan));
}
}