初识反射

通过反射可以获取类的Class对象, 一个类在内存中只有一个Class对象,Class对象不能开发者自己创建, 只能获取, 一个类被加载后类的整个结构都将被封装在Class对象中

获得Class对象的几种方法

  1. public class GetClass {
  2. public static void main(String[] args) throws ClassNotFoundException {
  3. //1.通过 对象.getClass() 获得
  4. Teacher william = new Teacher("william");
  5. Class c1 = william.getClass();
  6. System.out.println(c1);
  7. System.out.println("c1.hashCode() = " + c1.hashCode());
  8. //2.Class.forName(String className) 获得
  9. Class c2 = Class.forName("com.cqu.william.AnnotationAndReflection.Student");
  10. System.out.println("c2.hashCode() = " + c2.hashCode());
  11. //3.通过 类名.class 获得
  12. Class c3 = Student.class;
  13. System.out.println(c3);
  14. System.out.println("c3.hashCode() = " + c3.hashCode()); //同一个类的Class的hashcode相同
  15. //4.基本内置类型的包装类都有一个TYPE属性
  16. Class<Integer> c4 = Integer.TYPE;
  17. System.out.println("c4 = " + c4);
  18. //5.通过Class.getSuperclass()可以获得其父类的Class对象
  19. Class c5 = c2.getSuperclass();
  20. System.out.println("c5 = " + c5);
  21. }
  22. }
  23. class Person {
  24. public String name;
  25. public Person() {
  26. }
  27. public Person(String name) {
  28. this.name = name;
  29. }
  30. }
  31. class Student extends Person {
  32. public Student(String name) {
  33. super(name);
  34. }
  35. }
  36. class Teacher extends Person {
  37. public Teacher(String name) {
  38. super(name);
  39. }
  40. }

Class.getxxx()

  1. public class GetName {
  2. public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
  3. Class c1 = Class.forName("com.cqu.william.AnnotationAndReflection.User");
  4. //获得类的名字
  5. System.out.println("c1.getName() = " + c1.getName());//获得包名+类名
  6. System.out.println("c1.getSimpleName() = " + c1.getSimpleName());//获得类名
  7. //获得类的属性
  8. Field[] fields = c1.getFields(); //只能获得public属性的数组
  9. for (Field field : fields) {
  10. System.out.println(field);
  11. }
  12. System.out.println("======================================");
  13. fields = c1.getDeclaredFields(); //获得所有属性的数组
  14. for (Field field : fields) {
  15. System.out.println(field);
  16. }
  17. System.out.println("======================================");
  18. Field name = c1.getDeclaredField("name");
  19. System.out.println(name);//获得指定属性
  20. System.out.println("======================================");
  21. // 获得方法
  22. Method[] methods = c1.getMethods();//获得本类及父类的所有public方法的数组
  23. for (Method method : methods) {
  24. System.out.println(method);
  25. }
  26. System.out.println("======================================");
  27. Field[] declaredFields = c1.getDeclaredFields();//获得本类的所有方法的数组
  28. for (Field declaredField : declaredFields) {
  29. System.out.println(declaredField);
  30. }
  31. System.out.println("======================================");
  32. //获得所有public构造器的数组
  33. Constructor[] constructors = c1.getConstructors();
  34. for (Constructor constructor : constructors) {
  35. System.out.println(constructor);
  36. }
  37. System.out.println("======================================");
  38. //获得所有public构造器的数组
  39. Constructor[] declaredConstructors = c1.getDeclaredConstructors();
  40. for (Constructor declaredConstructor : declaredConstructors) {
  41. System.out.println(declaredConstructor);
  42. }
  43. }
  44. }

动态创造对象

  1. public class Dyn {
  2. private static Object william;
  3. public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
  4. Class c1 = Class.forName("com.cqu.william.AnnotationAndReflection.User");
  5. //使用newInstance()动态构造对象
  6. User user = (User) c1.newInstance();
  7. System.out.println(user);
  8. //使用getDeclaredConstructor(params)获取构造器, 通过构造器创建对象
  9. Constructor c = c1.getDeclaredConstructor(String.class, int.class, int.class);
  10. Object william = c.newInstance("william", 20193818, 19);
  11. //使用getDeclaredMethod()获取指定方法
  12. Method setName = c1.getDeclaredMethod("setName", String.class);
  13. //使用invoke调用william对象的setName方法,参数为"ABC"
  14. setName.invoke(william, "ABC");
  15. //使用getDeclaredField()获得字段
  16. Field name = c1.getDeclaredField("name");
  17. //setAccessible(true)关闭反射的检测
  18. name.setAccessible(true);
  19. name.set(william, "william");
  20. }
  21. }

反射的执行表现

反射使得执行效率大大降低, 通过关闭检测setAccessible(true)能稍微提升

  1. // 分别使用三种方式执行10亿次循环, 记录所用的时间, 比较执行效率
  2. public class Performance {
  3. public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
  4. test01();
  5. test02();
  6. test03();
  7. }
  8. //普通方式调用getName()
  9. static void test01() {
  10. User user = new User();
  11. long startTime = System.currentTimeMillis();
  12. for (int i = 0; i < 1000000000; i++) {
  13. user.getName();
  14. }
  15. long endTime = System.currentTimeMillis();
  16. System.out.println("普通方式执行循环体10亿次 " + (endTime - startTime) + "ms");
  17. }
  18. //反射方式调用getName()
  19. static void test02() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
  20. User user = new User();
  21. //通过getClass()得到user的Class对象
  22. Class c1 = user.getClass();
  23. // getDeclaredMethod("getName")得到User.getName()方法
  24. Method getName = c1.getDeclaredMethod("getName");
  25. long startTime = System.currentTimeMillis();
  26. for (int i = 0; i < 1000000000; i++) {
  27. // getName.invoke(user)表示对user对象使用getName方法
  28. getName.invoke(user);
  29. }
  30. long endTime = System.currentTimeMillis();
  31. System.out.println("反射方式执行循环体10亿次 " + (endTime - startTime) + "ms");
  32. }
  33. //反射方式调用getName()并关闭检测
  34. static void test03() throws NoSuchMethodException {
  35. User user = new User();
  36. Class c3 = user.getClass();
  37. Method getName = c3.getDeclaredMethod("getName");
  38. //setAccessible(true)关闭检测
  39. getName.setAccessible(true);
  40. long startTime = System.currentTimeMillis();
  41. for (int i = 0; i < 1000000000; i++) {
  42. user.getName();
  43. }
  44. long endTime = System.currentTimeMillis();
  45. System.out.println("关闭检测执行循环体10亿次 " + (endTime - startTime) + "ms");
  46. }
  47. }