一、反射类的概念及作用
1.什么是反射类
动态获取类或者对象的信息(属性和方法),以及动态操作对象的属性和方法的类,动态分析和使用类的信息的类
注:动态是指在java运行状态
2.反射类的作用
- 动态获取:动态获取类或对象的属性和方法
- 动态调用:动态调用对象的属性和方法
3.反射的使用场景
- 操作因访问权限限制的属性和方法;
- 实现自定义注解;
- 动态加载第三方jar包
- 按需加载类,节省编译和初始化时间;
二、反射技术的使用
1.反射主要涉及的类
反射技术的核心技术是Class对象,每个类在定义以后都有各自的Class对象
2.反射技术主要框架
3.定义一个实体类
1. `package main.java.com.shixinke.java.demo.reflect;` 3. `public class User {` 4. `public String platformNo = "WEB";` 5. `private Long userId;` 6. `private String nickname;` 7. `private String password;` 8. `private Character gender;` 9. `private String email;` 11. `public Long getUserId() {` 12. `return userId;` 13. `}` 15. `public void setUserId(Long userId) {` 16. `this.userId = userId;` 17. `}` 19. `public String getNickname() {` 20. `return nickname;` 21. `}` 23. `public void setNickname(String nickname) {` 24. `this.nickname = nickname;` 25. `}` 27. `public String getPassword() {` 28. `return password;` 29. `}` 31. `public void setPassword(String password) {` 32. `this.password = password;` 33. `}` 35. `public Character getGender() {` 36. `return gender;` 37. `}` 39. `public void setGender(Character gender) {` 40. `this.gender = gender;` 41. `}` 43. `public String getEmail() {` 44. `return email;` 45. `}` 47. `public void setEmail(String email) {` 48. `this.email = email;` 49. `}` 51. `private void setGender(int gender) {` 52. `if (gender == 1) {` 53. `this.gender = 'M';` 54. `} else {` 55. `this.gender = 'F';` 56. `}` 57. `}` 58. `}`
4.获取类的Class对象
(1)通过Class.forName()方法来获取 在面试中被问到并发知识的时候,大多都会被问到“请你说一下自己对于AQS原理的理解”。下面给大家一个示例供大家参加,面试不是背题,大家一定要假如自己的思想,即使加入不了自己的思想也要保证自己能够通俗的讲出来而不是背出来。在此我向大家推荐一个架构学习交流圈。交流学习伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
- 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. `}` 6. `Field[] allFields = cls.getDeclaredFields();` 7. `for (Field field : allFields) {` 8. `System.out.println(field.getName()); //[platformNo userId nickname password gender email]` 9. `}`
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. `}` 9. `/**` 10. `* 2.获取所有方法` 11. `*/` 12. `Method[] allMethods = cls.getDeclaredMethods();` 13. `for (Method m : allMethods) {` 14. `System.out.println(m.getName());` 15. `}` 17. `/**` 18. `* 3.获取某个指定方法名的方法对象(必须是非私有方法)` 19. `* 第1个参数为方法名,第2个参数及以后的表示方法中的参数的类型` 20. `*/` 21. `Method setGenderMethod = cls.getMethod("setGender", Character.class);` 22. `System.out.println(setGenderMethod.getParameterCount());` 24. `/**` 25. `* 4.获取某个指定方法名的方法对象(既可以是公有也可以是私有)` 26. `*/` 27. `Method setGenderAllMethod = cls.getDeclaredMethod("setGender", int.class);` 28. `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());` 7. `/**` 8. `* 2.获取参数对象数组` 9. `*/` 10. `for (Parameter p : m.getParameters()) {` 11. `System.out.println(p.getName()); //获取参数名称` 12. `System.out.println(p.getType()); //获取参数的类型` 13. `System.out.println(p.getAnnotations()); //获取参数的注解` 14. `}` 16. `/**` 17. `* 获取返回值类型` 18. `*/` 19. `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. `}` 8. `/**` 9. `* 2.获取使用的注解数组对象` 10. `*/` 11. `for (Annotation a : cls.getAnnotations()) {` 12. `System.out.println(a.getClass().getName());` 13. `}`
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)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性