java 反射
Class 类:类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。一个Class对象表示表示的是一种类型,但这个类型未必是一种类,比如int.class是一个Class对象,而int不是类。
Field 类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
Constructor 类:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和 Field 类不同,Field 类封装了反射类的属性,而 Constructor 类则封装了反射类的构造方法。
Method 类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法。这个类不难理解,它是用来封装反射类方法的一个类。
如何获得字节码?
Class cls = Xxx.class;
Class cls = xx.getClass();
Class.forname(类名); // 返回字节码:若内存中有加载该类,则他找到该类的字节码并返回,若无,则找到该类的路径,加载后返回。
要区别一个概念,这里获得的是类的字节码,与具体的对象无关。
如何获得实例?
Test t1=new Test();
Object t2 =t1.getClass().newInstance();
Object t3 =Class.forName("Test").newInstance();
newInstance方法调用没有参数的构造器,如果带参数就需要使用Constructor类。
Class类中的getFields、getMethods、getConstructors将返回类支持的public域、方法、和构造器数组,包括超类的公有成员。
Class类中的getDeclareFields、getDeclareMethods、getDeclareConstructors将返回类中声明的全部域、方法、和构造器数组,其中包括私有的和保护的,但不包括超类的成员。
Field、Method、Constructor都有一个getModifiers方法,可以使用其枚举值判断修饰符,或者Modifier.toString方法等解析。
AccessibleObjecte是Field、Method、Constructor公共超类,调用setAccessible(true)方法后可以对实例的保护和私有成员设置新值。这个特性是为调试、持久存储相似机制提供的。
import java.lang.reflect.AccessibleObject; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import javax.accessibility.AccessibleRole; public class ReflectTest { public static int a = 47; private String str = "hello"; public ReflectTest() { } public ReflectTest(String str) { this.str = str; } public String getStr(String str) { return this.str + "," + str; } public String getStr() { return str; } public static void MethodTest(Object object) { }; public static void main(String[] args) throws Exception { ReflectTest instance = new ReflectTest(); // 获取字节码 Class clazz = Class.forName("ReflectTest"); // 获取字段信息 Field fieldA = clazz.getField("a"); fieldA.getName(); fieldA.getType(); Modifier.toString(fieldA.getModifiers()); fieldA.getInt(instance); fieldA.get(instance); //设置私有成员 Field fieldStr = clazz.getDeclaredField("str"); fieldStr.setAccessible(true); // AccessibleObject.setAccessible(array, flag) fieldStr.set(instance, "abc"); // 根据字节码构造实例 Constructor<ReflectTest> constructor = clazz.getConstructor(); instance = constructor.newInstance();// 无参 instance = (ReflectTest) clazz.newInstance(); // 无参 constructor = clazz.getConstructor(String.class);// 有参 instance = constructor.newInstance("world"); // 调用指针函数 Method method1 = instance.getClass().getMethod("getStr"); method1.invoke(instance);//无参 method1 = instance.getClass().getMethod("getStr", String.class); method1.invoke(instance, "String str");// 有参 method1 = instance.getClass().getMethod("MethodTest", Object.class); method1.invoke(null, "object");// 静态 } // 使用反射编写通用的数组代码 static Object GoodArryGrow(Object src) { Class cl = src.getClass(); if (!cl.isArray()) return null; Class componentType = cl.getComponentType(); int length = Array.getLength(src); int newLength = length * 11 / 10 + 10; Object dest = Array.newInstance(componentType, newLength); System.arraycopy(src, 0, dest, 0, newLength); return dest; } }