初识反射
通过反射可以获取类的Class对象, 一个类在内存中只有一个Class对象,Class对象不能开发者自己创建, 只能获取, 一个类被加载后类的整个结构都将被封装在Class对象中
获得Class对象的几种方法
public class GetClass {public static void main(String[] args) throws ClassNotFoundException {//1.通过 对象.getClass() 获得Teacher william = new Teacher("william");Class c1 = william.getClass();System.out.println(c1);System.out.println("c1.hashCode() = " + c1.hashCode());//2.Class.forName(String className) 获得Class c2 = Class.forName("com.cqu.william.AnnotationAndReflection.Student");System.out.println("c2.hashCode() = " + c2.hashCode());//3.通过 类名.class 获得Class c3 = Student.class;System.out.println(c3);System.out.println("c3.hashCode() = " + c3.hashCode()); //同一个类的Class的hashcode相同//4.基本内置类型的包装类都有一个TYPE属性Class<Integer> c4 = Integer.TYPE;System.out.println("c4 = " + c4);//5.通过Class.getSuperclass()可以获得其父类的Class对象Class c5 = c2.getSuperclass();System.out.println("c5 = " + c5);}}class Person {public String name;public Person() {}public Person(String name) {this.name = name;}}class Student extends Person {public Student(String name) {super(name);}}class Teacher extends Person {public Teacher(String name) {super(name);}}
Class.getxxx()
public class GetName {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {Class c1 = Class.forName("com.cqu.william.AnnotationAndReflection.User");//获得类的名字System.out.println("c1.getName() = " + c1.getName());//获得包名+类名System.out.println("c1.getSimpleName() = " + c1.getSimpleName());//获得类名//获得类的属性Field[] fields = c1.getFields(); //只能获得public属性的数组for (Field field : fields) {System.out.println(field);}System.out.println("======================================");fields = c1.getDeclaredFields(); //获得所有属性的数组for (Field field : fields) {System.out.println(field);}System.out.println("======================================");Field name = c1.getDeclaredField("name");System.out.println(name);//获得指定属性System.out.println("======================================");// 获得方法Method[] methods = c1.getMethods();//获得本类及父类的所有public方法的数组for (Method method : methods) {System.out.println(method);}System.out.println("======================================");Field[] declaredFields = c1.getDeclaredFields();//获得本类的所有方法的数组for (Field declaredField : declaredFields) {System.out.println(declaredField);}System.out.println("======================================");//获得所有public构造器的数组Constructor[] constructors = c1.getConstructors();for (Constructor constructor : constructors) {System.out.println(constructor);}System.out.println("======================================");//获得所有public构造器的数组Constructor[] declaredConstructors = c1.getDeclaredConstructors();for (Constructor declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);}}}
动态创造对象
public class Dyn {private static Object william;public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {Class c1 = Class.forName("com.cqu.william.AnnotationAndReflection.User");//使用newInstance()动态构造对象User user = (User) c1.newInstance();System.out.println(user);//使用getDeclaredConstructor(params)获取构造器, 通过构造器创建对象Constructor c = c1.getDeclaredConstructor(String.class, int.class, int.class);Object william = c.newInstance("william", 20193818, 19);//使用getDeclaredMethod()获取指定方法Method setName = c1.getDeclaredMethod("setName", String.class);//使用invoke调用william对象的setName方法,参数为"ABC"setName.invoke(william, "ABC");//使用getDeclaredField()获得字段Field name = c1.getDeclaredField("name");//setAccessible(true)关闭反射的检测name.setAccessible(true);name.set(william, "william");}}
反射的执行表现
反射使得执行效率大大降低, 通过关闭检测setAccessible(true)能稍微提升
// 分别使用三种方式执行10亿次循环, 记录所用的时间, 比较执行效率public class Performance {public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {test01();test02();test03();}//普通方式调用getName()static void test01() {User user = new User();long startTime = System.currentTimeMillis();for (int i = 0; i < 1000000000; i++) {user.getName();}long endTime = System.currentTimeMillis();System.out.println("普通方式执行循环体10亿次 " + (endTime - startTime) + "ms");}//反射方式调用getName()static void test02() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {User user = new User();//通过getClass()得到user的Class对象Class c1 = user.getClass();// getDeclaredMethod("getName")得到User.getName()方法Method getName = c1.getDeclaredMethod("getName");long startTime = System.currentTimeMillis();for (int i = 0; i < 1000000000; i++) {// getName.invoke(user)表示对user对象使用getName方法getName.invoke(user);}long endTime = System.currentTimeMillis();System.out.println("反射方式执行循环体10亿次 " + (endTime - startTime) + "ms");}//反射方式调用getName()并关闭检测static void test03() throws NoSuchMethodException {User user = new User();Class c3 = user.getClass();Method getName = c3.getDeclaredMethod("getName");//setAccessible(true)关闭检测getName.setAccessible(true);long startTime = System.currentTimeMillis();for (int i = 0; i < 1000000000; i++) {user.getName();}long endTime = System.currentTimeMillis();System.out.println("关闭检测执行循环体10亿次 " + (endTime - startTime) + "ms");}}
