一、反射类的概念及作用
1.什么是反射类
动态获取类或者对象的信息(属性和方法),以及动态操作对象的属性和方法的类,动态分析和使用类的信息的类
注:动态是指在java运行状态
2.反射类的作用
- 动态获取:动态获取类或对象的属性和方法
- 动态调用:动态调用对象的属性和方法
3.反射的使用场景
- 操作因访问权限限制的属性和方法;
- 实现自定义注解;
- 动态加载第三方jar包
- 按需加载类,节省编译和初始化时间;
二、反射技术的使用
1.反射主要涉及的类
反射技术的核心技术是Class对象,每个类在定义以后都有各自的Class对象
2.反射技术主要框架
3.定义一个实体类
package main.java.com.shixinke.java.demo.reflect;
public class User {
public String platformNo = "WEB";
private Long userId;
private String nickname;
private String password;
private Character gender;
private String email;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Character getGender() {
return gender;
}
public void setGender(Character gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
private void setGender(int gender) {
if (gender == 1) {
this.gender = 'M';
} else {
this.gender = 'F';
}
}
}
4.获取类的Class对象
(1)通过Class.forName()方法来获取
- forName(类的路径)
/**
* 1.通过Class.forName的形式来获取Class对象
*/
Class cls = Class.forName("main.java.com.shixinke.java.demo.reflect.User");
(2)通过类名.class来获取
/**
* 2.通过类名.class来获取Class对象
*/
Class clz = User.class;
(3)通过类对象.getClass()来获取
/**
* 3.通过类对象.getClass()方法获取Class对象
*/
User user = new User();
Class clazz = user.getClass();
5.通过类的Class对象获取类本身的信息
- getName()获取类的名称
System.out.println(cls.getName()); //main.java.com.shixinke.java.demo.reflect.User
System.out.println(cls.getSuperclass()); //class java.lang.Object
System.out.println(cls.getCanonicalName()); //main.java.com.shixinke.java.demo.reflect.User
6.通过类的Class对象获取类的属性信息
- getFields() : 获取类中的所有非私有的属性
- getDecalaredFields() : 获取类中所有的属性(包括私有和仅有属性)
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.println(field.getName()); //platformNo : 只能获取非私有的属性
}
Field[] allFields = cls.getDeclaredFields();
for (Field field : allFields) {
System.out.println(field.getName()); //[platformNo userId nickname password gender email]
}
7.通过类的Class对象获取类的方法
- getMethods() : 获取所有的非私有方法对象数组
- getDeclaredMethods() : 获取所有的方法对象数组
- getMethod(methodName):获取指定方法名对应的非私有方法对象
- getDeclaredMethod(methodName):获取指定方法名对应的方法对象
/**
* 1.获取所有非私有方法
*/
Method[] methods = cls.getMethods();
for (Method m : methods) {
System.out.println(m.getName());
}
/**
* 2.获取所有方法
*/
Method[] allMethods = cls.getDeclaredMethods();
for (Method m : allMethods) {
System.out.println(m.getName());
}
/**
* 3.获取某个指定方法名的方法对象(必须是非私有方法)
* 第1个参数为方法名,第2个参数及以后的表示方法中的参数的类型
*/
Method setGenderMethod = cls.getMethod("setGender", Character.class);
System.out.println(setGenderMethod.getParameterCount());
/**
* 4.获取某个指定方法名的方法对象(既可以是公有也可以是私有)
*/
Method setGenderAllMethod = cls.getDeclaredMethod("setGender", int.class);
System.out.println(setGenderAllMethod.getParameterCount());
8.方法对象(即Method对象)
- 获取参数相关的属性:
- 获取参数个数:getParameterCount()
- 获取参数数组对象:getParameters()
- 获取返回值相关的属性
- 获取返回值的类型:getReturnType()
Method m = cls.getMethod("setGender", Character.class);
/**
* 1.获取参数个数
*/
System.out.println(m.getParameterCount());
/**
* 2.获取参数对象数组
*/
for (Parameter p : m.getParameters()) {
System.out.println(p.getName()); //获取参数名称
System.out.println(p.getType()); //获取参数的类型
System.out.println(p.getAnnotations()); //获取参数的注解
}
/**
* 获取返回值类型
*/
System.out.println(m.getReturnType());
9.获取类的其他属性
- 获取实现的接口数组对象: getInterfaces()
- 获取使用的注解数组对象: getAnnotations()
/**
* 1.获取实现的接口数组对象
*/
for (Class c : cls.getInterfaces()) {
System.out.println(c.getName());
}
/**
* 2.获取使用的注解数组对象
*/
for (Annotation a : cls.getAnnotations()) {
System.out.println(a.getClass().getName());
}
10.创建类的对象(实例化对象)
(1)通过Class对象的newInstance()
User user = (User)cls.newInstance();
user.setEmail("ishixinke@qq.com");
System.out.println(user.getEmail()); //ishixinke@qq.com
(2)通过Constructor对象的newInstance方法
- 通过Class对象的getConstructor方法获取Constructor对象
- 通过Constructor对象的newInstance方法来实例化对象
Constructor constructor = cls.getConstructor();
User user = (User) constructor.newInstance();
user.setEmail("ishixinke@qq.com");
System.out.println(user.getEmail()); //ishixinke@qq.com
11.通过类的对象来调用属性和方法
- 通过Class类对象创建类实现类的实例化,得到类的实例
- 通过类的实例来操作属性和方法
User user = (User)cls.newInstance();
user.setEmail("ishixinke@qq.com");
System.out.println(user.getEmail()); //ishixinke@qq.com
三、反射的优点及缺点
1.反射的优点
- 灵活、自由度高:不受类的访问权限限制,想对类做啥就做啥
2.反射的缺点
- (1)使用反射的性能较低
- (2)使用反射相对来说不安全
- (3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性