前言
在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”
博客主页:KC老衲爱尼姑的博客主页
共勉:talk is cheap, show me the code
作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
文章目录
- 反射
- 定义
- 基本使用
- 获取类
- 获取构造器
- 获取成员变量
- 获取成员方法
- 使用场景
反射
定义
Java的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然都可以拿到,我们就可以修改类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
基本使用
获取类
在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的。因为对象都是通过类创建而来的,拿到了Class对象,并对其解析就可以获取类的成员属性,成员方法,构造器。Class对象存在的位置具体如下图。
获取类有三种方法
- 使用 Class.forName(“类的全路径名”); 静态方法。
- 使用类名.class
- 使用对象.getClass();
使用演示
首先创建一个User类,便于后期使用
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String username;
private String password;
public int age ;
public String pr(String username){
return username;
}
}
开始使用上述三种方法获取User的类对象
public class ClassDemo {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> user = Class.forName("org.example.Functional.model.User");
Class<User> userClass = User.class;
User user2 = new User("user2", "11");
Class<? extends User> aClass = user2.getClass();
System.out.println(user);
System.out.println(userClass);
System.out.println(aClass);
}
}
获取构造器
获取构造器的方法如下
方法 | 说明 |
Constructor<?>[] getConstructors() | 返回所有构造器对象的数组(只能拿public的) |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造器对象的数组,存在就能拿到 |
Constructor getConstructor(Class<?>… parameterTypes) | 返回单个构造器对象(只能拿public的) |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 返回单个构造器对象,存在就能拿到 |
使用演示
import java.lang.reflect.Constructor;
public class ConstructorsDemo {
public static void main(String[] args) throws NoSuchMethodException {
//1.反射第一步:获取这个类的Class对象
Class<User> userClass = User.class;
//获取类的无参构造
Constructor<User> declaredConstructor = userClass.getDeclaredConstructor();
//设置禁止访问权限
declaredConstructor.setAccessible(true);
//得到类名称和参数个数
System.out.println(declaredConstructor.getName()+"->"+declaredConstructor.getParameterCount());
//获取有参构造
Constructor<User> declaredConstructor1 = userClass.getConstructor(String.class, String.class);
//设置禁止访问权限
declaredConstructor1.setAccessible(true);
//得到类名称和参数个数
System.out.println(declaredConstructor1.getName()+"->"+declaredConstructor1.getParameterCount());
Constructor<?>[] constructors = userClass.getConstructors();
Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
System.out.println(constructors[1]);
System.out.println(constructors[0]);
System.out.println(declaredConstructors[1]);
System.out.println(declaredConstructors[0]);
}
}
运行结果:
获取构造器的作用依旧是为了初始化对象返回
Constructor类中用于创建对象的方法
方法 | 说明 |
T newInstance(Object… initargs) | 根据指定的构造器创建对象 |
public void setAccessible(boolean flag) | 设置为true,表示取消访问检查,进行暴力反射 |
使用演示
将User的有参构造设置为私有,并且不设置访问检查
public class ConstructorsDemo2 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.反射第一步:获取这个类的Class对象
Class<User> userClass = User.class;
Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, String.class);
User user = declaredConstructor1.newInstance( "sdf","211");
System.out.println(user.toString());
}
}
运行结果:
取消访问检查后
public class ConstructorsDemo2 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.反射第一步:获取这个类的Class对象
Class<User> userClass = User.class;
Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, String.class);
//设置禁止访问权限
declaredConstructor1.setAccessible(true);
User user = declaredConstructor1.newInstance( "sdf","211");
System.out.println(user.toString());
}
}
运行结果:
如果是非public的构造器,需要打开权限,然后才能创建对象。反射是Java的后门破坏的封装性,私有的也可以构造方法也可以执行了。
获取成员变量
Class类中用于获取成员变量的方法
方法 | 说明 |
Field[] getFields() | 返回所有成员变量对象的数组(只能拿public的) |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
Field getField(String name) | 返回单个成员变量对象(只能拿public的) |
Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
使用演示
public class AttributeDemo {
public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {
//1.反射第一步:获取这个类的Class对象
Class<User> userClass = User.class;
Field[] fields = userClass.getFields();
for (Field field : fields) {
System.out.println(field.getName()+"-->"+field.getType());
}
Field[] declaredFields = userClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName()+"-->"+declaredField.getType());
}
//定位某个变量
Field age = userClass.getField("age");
Field username = userClass.getDeclaredField("username");
Field password = userClass.getDeclaredField("password");
User user = new User();
//设置私有变量的访问
username.setAccessible(true);
password.setAccessible(true);
//赋值
username.set(user,"sdf");
password.set(user,"ss12");
age.set(user,90);
System.out.println(user);
//取值
String o = (String)username.get(user);
System.out.println(o);
}
}
运行结果:
私有的成员变量依旧需要开启访问权限
获取成员方法
Class类中用于获取成员变量的方法、
方法 | 说明 |
Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
Method getMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象(只能拿public的) |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
使用演示
public class MethodDemo {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.反射第一步:获取这个类的Class对象
Class<User> userClass = User.class;
//获取类的成员方法
Method[] methods = userClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName() + " "+method.getParameterCount()
+method.getReturnType());
}
//获取某个对象方法
Method pr = userClass.getDeclaredMethod("pr",String.class);
System.out.println(pr.getName() + " "+pr.getParameterCount()+" "
+pr.getReturnType());
User user = new User();
pr.setAccessible(true);
//调用方法,用user对象
Object invoke = pr.invoke(user,"java");
System.out.println(invoke);
}
}
使用场景
- 在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统****应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法 。
- 反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。
各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。