java反射的作用及使用详解

java反射的知识点

一、反射类的概念及作用

1.什么是反射类

动态获取类或者对象的信息(属性和方法),以及动态操作对象的属性和方法的类,动态分析和使用类的信息的类

注:动态是指在java运行状态

2.反射类的作用
  • 动态获取:动态获取类或对象的属性和方法
  • 动态调用:动态调用对象的属性和方法
3.反射的使用场景
  • 操作因访问权限限制的属性和方法;
  • 实现自定义注解;
  • 动态加载第三方jar包
  • 按需加载类,节省编译和初始化时间;

二、反射技术的使用

1.反射主要涉及的类

java反射的主要的类

反射技术的核心技术是Class对象,每个类在定义以后都有各自的Class对象

2.反射技术主要框架

java反射核心技术框架

3.定义一个实体类
  1. package main.java.com.shixinke.java.demo.reflect;
  2. public class User {
  3. public String platformNo = "WEB";
  4. private Long userId;
  5. private String nickname;
  6. private String password;
  7. private Character gender;
  8. private String email;
  9. public Long getUserId() {
  10. return userId;
  11. }
  12. public void setUserId(Long userId) {
  13. this.userId = userId;
  14. }
  15. public String getNickname() {
  16. return nickname;
  17. }
  18. public void setNickname(String nickname) {
  19. this.nickname = nickname;
  20. }
  21. public String getPassword() {
  22. return password;
  23. }
  24. public void setPassword(String password) {
  25. this.password = password;
  26. }
  27. public Character getGender() {
  28. return gender;
  29. }
  30. public void setGender(Character gender) {
  31. this.gender = gender;
  32. }
  33. public String getEmail() {
  34. return email;
  35. }
  36. public void setEmail(String email) {
  37. this.email = email;
  38. }
  39. private void setGender(int gender) {
  40. if (gender == 1) {
  41. this.gender = 'M';
  42. } else {
  43. this.gender = 'F';
  44. }
  45. }
  46. }
4.获取类的Class对象
(1)通过Class.forName()方法来获取
  • forName(类的路径)
  1. /**
  2. * 1.通过Class.forName的形式来获取Class对象
  3. */
  4. Class cls = Class.forName("main.java.com.shixinke.java.demo.reflect.User");
(2)通过类名.class来获取
  1. /**
  2. * 2.通过类名.class来获取Class对象
  3. */
  4. Class clz = User.class;
(3)通过类对象.getClass()来获取
  1. /**
  2. * 3.通过类对象.getClass()方法获取Class对象
  3. */
  4. User user = new User();
  5. Class clazz = user.getClass();
5.通过类的Class对象获取类本身的信息
  • getName()获取类的名称
  1. System.out.println(cls.getName()); //main.java.com.shixinke.java.demo.reflect.User
  2. System.out.println(cls.getSuperclass()); //class java.lang.Object
  3. System.out.println(cls.getCanonicalName()); //main.java.com.shixinke.java.demo.reflect.User
6.通过类的Class对象获取类的属性信息
  • getFields() : 获取类中的所有非私有的属性
  • getDecalaredFields() : 获取类中所有的属性(包括私有和仅有属性)
  1. Field[] fields = cls.getFields();
  2. for (Field field : fields) {
  3. System.out.println(field.getName()); //platformNo : 只能获取非私有的属性
  4. }
  5. Field[] allFields = cls.getDeclaredFields();
  6. for (Field field : allFields) {
  7. System.out.println(field.getName()); //[platformNo userId nickname password gender email]
  8. }
7.通过类的Class对象获取类的方法
  • getMethods() : 获取所有的非私有方法对象数组
  • getDeclaredMethods() : 获取所有的方法对象数组
  • getMethod(methodName):获取指定方法名对应的非私有方法对象
  • getDeclaredMethod(methodName):获取指定方法名对应的方法对象
  1. /**
  2. * 1.获取所有非私有方法
  3. */
  4. Method[] methods = cls.getMethods();
  5. for (Method m : methods) {
  6. System.out.println(m.getName());
  7. }
  8. /**
  9. * 2.获取所有方法
  10. */
  11. Method[] allMethods = cls.getDeclaredMethods();
  12. for (Method m : allMethods) {
  13. System.out.println(m.getName());
  14. }
  15. /**
  16. * 3.获取某个指定方法名的方法对象(必须是非私有方法)
  17. * 第1个参数为方法名,第2个参数及以后的表示方法中的参数的类型
  18. */
  19. Method setGenderMethod = cls.getMethod("setGender", Character.class);
  20. System.out.println(setGenderMethod.getParameterCount());
  21. /**
  22. * 4.获取某个指定方法名的方法对象(既可以是公有也可以是私有)
  23. */
  24. Method setGenderAllMethod = cls.getDeclaredMethod("setGender", int.class);
  25. System.out.println(setGenderAllMethod.getParameterCount());
8.方法对象(即Method对象)
  • 获取参数相关的属性:
    • 获取参数个数:getParameterCount()
    • 获取参数数组对象:getParameters()
  • 获取返回值相关的属性
    • 获取返回值的类型:getReturnType()
  1. Method m = cls.getMethod("setGender", Character.class);
  2. /**
  3. * 1.获取参数个数
  4. */
  5. System.out.println(m.getParameterCount());
  6. /**
  7. * 2.获取参数对象数组
  8. */
  9. for (Parameter p : m.getParameters()) {
  10. System.out.println(p.getName()); //获取参数名称
  11. System.out.println(p.getType()); //获取参数的类型
  12. System.out.println(p.getAnnotations()); //获取参数的注解
  13. }
  14. /**
  15. * 获取返回值类型
  16. */
  17. System.out.println(m.getReturnType());
9.获取类的其他属性
  • 获取实现的接口数组对象: getInterfaces()
  • 获取使用的注解数组对象: getAnnotations()
  1. /**
  2. * 1.获取实现的接口数组对象
  3. */
  4. for (Class c : cls.getInterfaces()) {
  5. System.out.println(c.getName());
  6. }
  7. /**
  8. * 2.获取使用的注解数组对象
  9. */
  10. for (Annotation a : cls.getAnnotations()) {
  11. System.out.println(a.getClass().getName());
  12. }
10.创建类的对象(实例化对象)
(1)通过Class对象的newInstance()
  1. User user = (User)cls.newInstance();
  2. user.setEmail("ishixinke@qq.com");
  3. System.out.println(user.getEmail()); //ishixinke@qq.com
(2)通过Constructor对象的newInstance方法
  • 通过Class对象的getConstructor方法获取Constructor对象
  • 通过Constructor对象的newInstance方法来实例化对象
  1. Constructor constructor = cls.getConstructor();
  2. User user = (User) constructor.newInstance();
  3. user.setEmail("ishixinke@qq.com");
  4. System.out.println(user.getEmail()); //ishixinke@qq.com
11.通过类的对象来调用属性和方法
  • 通过Class类对象创建类实现类的实例化,得到类的实例
  • 通过类的实例来操作属性和方法
  1. User user = (User)cls.newInstance();
  2. user.setEmail("ishixinke@qq.com");
  3. System.out.println(user.getEmail()); //ishixinke@qq.com

三、反射的优点及缺点

1.反射的优点
  • 灵活、自由度高:不受类的访问权限限制,想对类做啥就做啥
2.反射的缺点
  • (1)使用反射的性能较低
  • (2)使用反射相对来说不安全
  • (3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性