1.什么是反射
Java 反射(Reflection)是可以让我们在运行时获取类的方法、属性、父类、接口等类的内部信息的机制。也就是说,反射本质上是一个“反着来”的过程。我们通过new创建一个类的实例时,实际上是由Java虚拟机根据这个类的Class对象在运行时构建出来的,而反射是通过一个类的Class对象来获取它的定义信息,从而我们可以访问到它的属性、方法,知道这个类的父类、实现了哪些接口等信息。
反射是一种机制,利用反射机制动态的实例化对象、读写属性、调用方法、构造函数。
2.反射能干什么用
Java Reflection功能非常强大,并且非常有用,比如:
-
获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等
-
获取任意对象的属性,并且能改变对象的属性
-
调用任意对象的方法
-
判断任意一个对象所属的类
-
实例化任意一个类的对象
-
通过反射我们可以实现动态装配,降低代码的耦合度,动态代理等。
3.如何使用反射
一切与反射相关的代码都从获取类对应的字节码对象开始。
-
调用某个类的对象的getClass()方法,
-
调用类的class属性类获取该类对应的Class对象,
-
使用Class类中的forName()静态方法,
-
例如:
//读写属性、调用方法及构造函数。
//一切与反射相关的代码都从获取类对象开始
//1、类名.class
Class<Student> stuClass = Student.class;
//2、对象名.getClass
Student stu =new Student();
Class<? extends Student> stuClass = stu.getClass();
//3、Class.forname("类的全路径名")
Class<?> stuClass = Class.forName("com.zking.entity.Student");
System.out.println("获取类的全路径名:"+stuClass.getName());
System.out.println("获取简单类名:"+stuClass.getSimpleName());
System.out.println("获取包名:"+stuClass.getPackageName());
4.传统实例化与反射实例化区别
-
传统实例化对象
-
反射实例化对象
-
例如:
//3、传统实例化方式与反射实例化方式的区别
//1、传统
Student stu =new Student();
//反射
//获取类对象
Class<?> stuClass = Class.forName("com.zking.entity.Student");
//通过反射机制动态的实例化对象
Object stu = stuClass.newInstance();
1)Class.forName指定全路径名必须正确,否则将报ClassNotFoundException错误; 2)在运行期间,一个类,类对象只能创建一个
5.反射应用
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也成为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造函数 |
5.1.获取Field类相关
类名 | 用途 |
---|---|
getField(String name) | 获取某个公共的属性对象 |
getFields() | 获取所有公共的属性对象 |
getDeclaredField(String name) | 获取某个属性对象(public和非public) |
getDeclaredFields() | 获取所有属性对象(public和非public) |
setAccessible(boolean flag) | 默认值false,设置true使私有成员允许访问 |
set(Object,Object) | 属性赋值 |
get(Object) | 获取属性 |
-
属性赋值&&获取属性的案例
//读取属性(Field)
//获取类对象
Class<?> stuClass = Class.forName("com.zking.entity.Student");
//通过反射机制动态的实例化对象
Object stu = stuClass.newInstance();
//1)获取公共的单个属性
Field field = stuClass.getField("sname");
//2)获取公共的、私有的、受保护的、最终的、静态的等等单个属性
Field field = stuClass.getDeclaredField("sname");
//设置权限
field.setAccessible(true);
//3)获取所有公共的属性
Field[] fields = stuClass.getFields();
//4、获取所有类型的属性
Field[] fields = stuClass.getDeclaredFields();
for(Field field : fields){
System.out.println("属性名:"+field.getName());
System.out.println("属性类型:"+field.getType());
System.out.println("访问修饰符:"+field.getModifiers());
System.out.println("-------------------------");
}
//5、属性赋值
Field field = stuClass.getDeclaredField("sname");
//参数:1)实例化对象名2)赋的值
field.setAccessible(true);
field.set(stu,"man");
注:在对类中私有属性赋值时必须设置访问权限。
5.2.获取Method类相关
类名 | 用途 |
---|---|
getMethod(String name, Class<>… parameterTypes) | 获取该类某个公共的方法 |
getMethods() | 获取该类所有公共的方法 |
getDeclaredMethods(String name,Class<>… parameterTypes) | 获取该类某个方法(public和非public) |
getDeclaredMethod() | 获取该类所有方法(public和非public) |
setAccessible(boolean flag) | 默认值false,设置true使私有方法允许访问 |
invoke(Object obj, Object… args) | 执行方法 |
-
调用方法
//5、调用方法(Method)
//1)获取单个公共的方法
Method method = stuClass.getMethod("hello");
//2)获取单个公共的、私有的、受保护的等等方法
Method method = stuClass.getDeclaredMethod("hello", String.class);
Method method = stuClass.getDeclaredMethod("add", Integer.class,Integer.class);
//3)获取所有公共的方法
Method[] methods = stuClass.getMethods();
//2)获取所有公共的、私有的、受保护的等等方法
Method[] methods = stuClass.getDeclaredMethods();
for (Method method : methods){
System.out.println("方法名:"+method.getName());
System.out.println("访问修饰符:"+method.getModifiers());
System.out.println("返回类型:"+method.getReturnType());
System.out.println("方法参数数量:"+method.getParameterCount());
System.out.println("------------------------");
}
//5、调用方法
Method method = stuClass.getMethod("hello");
Method method = stuClass.getDeclaredMethod("add", Integer.class,Integer.class);
method.setAccessible(true);
//调用方法
//参数1:实例化对象名
//参数2:方法本身所需参数(可变参数)
Object returnValue = method.invoke(stu,1,5);
System.out.println(returnValue);
5.3.获取Constructor类相关
类名 | 用途 |
---|---|
getConstructor(Class<>… parameterTypes) | 获取该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获取该类的所有公共构造方法 |
getDeclaredConstructors(Class<>… parameterTypes) | 获取该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获取该类所有构造方法(public和非public) |
- 调用方法
// Constructor构造函数的相关案例
// 1)获取单个公共的构造函数
Constructor<?> constructor = stuClass.getConstructor();
// 2)获取单个公共的、私有的等等构造函数
Constructor<?> constructor = stuClass.getDeclaredConstructor(String.class);
// 3)获取所有公共的构造函数
Constructor<?>[] constructors = stuClass.getConstructors();
for (Constructor constructor : constructors){
System.out.println("方法名:"+constructor.getName());
System.out.println("访问修饰符:"+constructor.getModifiers());
System.out.println("参数数量:"+constructor.getParameterCount());
System.out.println("---------------------");
}
// 4)获取所有公共的、私有的等等构造函数
Constructor<?>[] constructors = stuClass.getDeclaredConstructors();
for (Constructor constructor : constructors){
System.out.println("方法名:"+constructor.getName());
System.out.println("访问修饰符:"+constructor.getModifiers());
System.out.println("参数数量:"+constructor.getParameterCount());
System.out.println("---------------------");
}
// 5)通过构造函数实例化对象
Constructor<?> constructor = stuClass.getConstructor();
Object newInstance = constructor.newInstance();