Java 反射机制可以让我们在编译期(Compile Time)之外的运行期(Runtime)检查类,接口,变量以及方法的信息。反射还可以让我们在运行期实例化对象,调用方法,通过调用 get/set 方法获取变量的值。
Class 对象
Class myObjectClass = MyObject.class; String className = ... ;//在运行期获取的类名字符串 Class class = Class.forName(className);//类的全名,这个全名包括类所在的包的名字 Class aClass = ... //全限定类名(包含包名) String className = aClass.getName();//全限定类名(包含包名) String simpleClassName = aClass.getSimpleName();//类的名字(不包含包名) int modifiers = aClass.getModifiers();//类的修饰符, 即public,private,static 等等的关键字 Modifier.isAbstract(int modifiers); Modifier.isFinal(int modifiers);//.......检查修饰符的类型 Package package = aClass.getPackage();//获取包的相关信息,比如包名,你也可以通过 Manifest 文件访问位于编译路径下 jar 包的指定信息,比如你可以在 Manifest 文件中指定包的版本编号 Class superclass = aClass.getSuperclass();//访问类的父类 Class[] interfaces = aClass.getInterfaces();//获取指定类所实现的接口集合,当前类的父类如果实现了接口,这些接口是不会在返回的 Class 集合中的,尽管实际上当前类其实已经实现了父类接口 Constructor[] constructors = aClass.getConstructors();//构造器 Method[] method = aClass.getMethods();//所有方法 Field[] method = aClass.getFields();//类的成员变量 Annotation[] annotations = aClass.getAnnotations();//类的注解
Java 构造器
Class aClass = ...//获取Class对象 Constructor[] constructors = aClass.getConstructors();//Constructor 数组包含每一个声明为公有的(Public)构造方法 Constructor constructor = aClass.getConstructor(new Class[]{String.class});//知道要访问的构造方法的参数类型,获取指定的构造方法 Class[] parameterTypes = constructor.getParameterTypes();//获取指定构造方法的方法参数信息 实例化一个类: Constructor constructor = MyObject.class.getConstructor(String.class); MyObject myObject = (MyObject)constructor.newInstance("constructor-arg1");
获取 Field 对象
Class aClass = ...//获取Class对象 Field[] methods = aClass.getFields(); Field field = aClass.getField("someField"); String fieldName = field.getName();//获取变量名称 Object fieldType = field.getType();//变量的类型 获取或设置(get/set)变量值: Class aClass = MyObject.class Field field = aClass.getField("someField"); MyObject objectInstance = new MyObject(); Object value = field.get(objectInstance);//获取实例objectInstance的变量someField的值 field.set(objetInstance, value);//设置变量值
获取 Method 对象
Class aClass = ...//获取Class对象 Method[] methods = aClass.getMethods();//数组包含了指定类中声明为公有的(public)的所有变量集合 Method method = aClass.getMethod("doSomething", new Class[]{String.class});//方法名称是“doSomething”,方法参数是 String 类型, 没有参数传入第二个参数传入null Class[] parameterTypes = method.getParameterTypes();//获取指定方法的方法参数 Class returnType = method.getReturnType();//获取指定方法的返回类型
//获取一个方法名为doSomesthing,参数类型为String的方法 Method method = MyObject.class.getMethod("doSomething", String.class); Object returnValue = method.invoke(null, "parameter-value1");//第一个参数为null表示该方法是静态方法
Getter 和
Setter
Setter 方法的名字以 set 开头,有一个方法参数。
不能直接寻找 getters 和 setters,你需要检查一个类所有的方法来判断哪个方法是 getters 和 setters
Getter 方法的名字以 get 开头,没有方法参数,返回一个值。
访问私有变量
Class.getDeclaredField(String name)方法或者 Class.getDeclaredFields()方法
privateStringField.setAccessible(true)这行代码,通过调用 setAccessible()方法会关闭指定类 Field 实例的反射访问检查,这行代码执行之后不论是私有的、受保护的以及包访问的作用域,你都可以在任何地方访问,即使你不在他的访问权限作用域之内。但是你如果你用一般代码来访问这些不在你权限作用域之内的代码依然是不可以的,在编译的时候就会报错。
访问私有方法
Class.getDeclaredField(String name)方法或者Class.getDeclaredFields()方法 privateStringField.setAccessible(true)这行代码,通过调用 setAccessible()方法会关闭指定类 Field 实例的反射访问检查,这行代码执行之后不论是私有的、受保护的以及包访问的作用域,你都可以在任何地方访问,即使你不在他的访问权限作用域之内。但是你如果你用一般代码来访问这些不在你权限作用域之内的代码依然是不可以的,在编译的时候就会报错。
数组
int[] intArray = (int[]) Array.newInstance(int.class, 3);//Java 反射机制通过 java.lang.reflect.Array 类来创建数组 Array.set(intArray, 0, 123); Array.set(intArray, 1, 456); Array.set(intArray, 2, 789);//访问数组中的元素,可以使用Array.get(…)和Array.set(…)方法来访问