这段时间在重温反射的知识,得到一些新的体会,对这方面知识也得到了进一步巩固,做个笔记下次方便找
一、反射的概念
- 在java中秉承着一切皆对象的原则,管理类的对象叫做Class,管理构造方法的类叫做Constructor,管理成员方法的类叫做Method,管理成员变量的类叫做Field,我们反射第一步就是拿到Class,再对其进行操作。
- 利用反射创建的对象可以不受访问修饰符的限制,调用使用类里面所有的内容
- 反射到底学些什么知识
- 如何获取class字节码文件的对象
- 利用反射获取构造方法并且创建对象
- 利用反射获取成员变量并且赋值获取值
- 利用反射获取成员方法并且调用方法
二、获取class对象的方法
- Class.forName("全类名");
- 类.class;
- 对象.getClass();
//1.Class.forName("全限类名")
Class<?> aClass = Class.forName("com.eva.entity.UserEntity");
log.debug("{}",aClass);
//2.类名.class
Class<UserEntity> userEntityClass = UserEntity.class;
log.debug("{}",userEntityClass);
//3.对象.getClass()
UserEntity userEntity = new UserEntity();
Class<? extends UserEntity> aClass1 = userEntity.getClass();
log.debug("{}",aClass1);
三、java源码和字节码文件区别
- java源码文件:我们自己写的代码
- 字节码文件:java源码编译后的class文件,存在于硬盘中,这个操作不需要我们自己操作,jdk有方法将java文件编译成class字节码文件
- 字节码文件对象:在内存当中运行的是class字节码文件,当class字节码文件加载到内存中的时候,jvm会自动创建出一个Class对象,用来管理class字节码文件,这个Class对象中包括了class字节码中的全部内容.我们反射得到的就是Class对象,因为jvm进行类加载只执行一次,所以这个Class对象在内存中是唯一的.
四、获取构造方法
方法作用 | 返回类型 | 方法名 |
得到所有公共构造方法 | Constructor<?>[] | getConstructors() |
得到所有构造方法 | Constructor<?>[] | getConstructors() |
得到单个公开构造方法 | Constructor<?>[] | getConstructors() |
得到单个非公开构造方法 | Constructor<T> | getDeclaredConstructor(Class<?>... parameterTypes) |
/**
* 反射得到类中的构造方法并且通过构造方法创建对象
*/
Class<UserEntity> userEntityClass = UserEntity.class;
//1.得到所有公共构造方法-->getConstructors()
Constructor<?>[] constructors = userEntityClass.getConstructors();
for (Constructor<?> constructor : constructors) {
log.debug("{}",constructor);
}
//2.得到所有的构造方法-->getDeclaredConstructors()
Constructor<?>[] declaredConstructors = userEntityClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
log.debug("{}",declaredConstructor);
}
//3.得到单个公开构造方法-->getConstructor(CLass<?>... parameterTypes)
try {
Constructor<UserEntity> constructor = userEntityClass.getConstructor(null);
log.debug("{}",constructor);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
//4.得到单个私有的构造方法-->getDeclaredConstructor(CLass<?>... parameterTypes)
try {
Constructor<UserEntity> declaredConstructor = userEntityClass.getDeclaredConstructor(String.class, String.class);
log.debug("{}",declaredConstructor);
declaredConstructor.setAccessible(true);
UserEntity userEntity = declaredConstructor.newInstance("张三", "男");
log.debug("{}",userEntity.song());
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
//5.得到单个受保护的构造方法-->getDeclaredConstructor(CLass<?>... parameterTypes)
try {
Constructor<UserEntity> declaredConstructor = userEntityClass.getDeclaredConstructor(String.class, String.class, int.class);
declaredConstructor.setAccessible(true);
UserEntity userEntity = declaredConstructor.newInstance("小红", "女", 18);
log.debug("{}",userEntity.getName());
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
五、获取成员方法
获取所有的公共方法 | Method[] | getMethods() |
获取所有的方法 | Method[] | getDeclaredMethods() |
获取单个的公共方法 | Method | getMethod(String name, Class<?>... parameterTypes) |
获取单个私有方法 | Method | getDeclaredMethod(String name, Class<?>... parameterTypes) |
/**
* 反射获取成员方法
*/
/*第一步:获取该类的Class对象*/
Class<UserEntity> userEntityClass = UserEntity.class;
/*1.获取所有的公共方法(包括父类所有的公共方法)*/
Method[] methods = userEntityClass.getMethods();
for (Method method : methods) {
log.debug("{}", method);
}
/*2.获取所有的方法(包括自身private修饰的方法,但是不包括父类的方法)*/
Method[] declaredMethods = userEntityClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
log.debug("{}", declaredMethod);
}
/*3.获取单个的公共方法-->getMethod(String name, Class<?>... parameterTypes)
参数一:方法名
参数二:形参类型
原因:为了区分重载方法,方法唯一性:方法名+形参类型和个数*/
Method song = userEntityClass.getMethod("song");
log.debug("{}", song);
/*4.获取单个私有方法*/
Method dance = userEntityClass.getDeclaredMethod("dance", String.class);
/*4.1 获取修饰符 public: 1 private: 2 protected: 4 */
int modifiers = dance.getModifiers();
log.debug("{}", modifiers);
/*4.2 获取方法名*/
String name = dance.getName();
log.debug("{}", name);
/*4.3 获取形参*/
Parameter[] parameters = dance.getParameters();
for (Parameter parameter : parameters) {
log.debug("{}", parameter);
}
/*4.4 获取抛出的异常*/
Class<?>[] exceptionTypes = dance.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
log.debug("{}", exceptionType);
}
/*4.5 使用方法
* Method类中用于创建对象的方法
* Object invoke(Object obj, Object... args):运行方法
* 参数一:表示方法的调用对象
* 参数二:调用方法的传递的参数(如果没有就不写)
* 返回值:方法的返回值(如果没有就不写)
*/
/*使用Class创建一个对象*/
UserEntity userEntity = userEntityClass.newInstance();
userEntity.setName("甄嬛");
//dance方法是私有的,用setAccessible(true)临时取消权限校验
dance.setAccessible(true);
//参数一 userEntity:表示方法的调用对象
//参数二 惊鸿舞:调用方法的传递的参数
String r = (String) dance.invoke(userEntity, "惊鸿舞");
log.debug("{}", r);
六、获取成员变量
/*第一步:获取Class对象*/
Class<UserEntity> userEntityClass = UserEntity.class;
/*1.获取所有公共属性*/
Field[] fields = userEntityClass.getFields();
for (Field field : fields) {
log.debug("{}", field);
}
/*2.获取所有属性*/
Field[] declaredFields = userEntityClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
log.debug("{}", declaredField);
}
/*3.获取单个私有属性*/
Field declaredField = userEntityClass.getDeclaredField("name");
/*3.1 获取属性值*/
UserEntity userEntity = userEntityClass.newInstance();
userEntity.setName("爱坤");
declaredField.setAccessible(true);
String value = (String) declaredField.get(userEntity);
log.debug("{}", value);
/*3.2 给属性赋值*/
declaredField.set(userEntity, "闲来");
value = (String) declaredField.get(userEntity);
log.debug("{}", value);