反射
1.什么是反射?
正射:知道某个类,类的地址,通过new关键字创建出对象,而后使用对象。
但是对于框架来说,处理哪些类并不知道,只结合它类的地址,他就能够获取类的信息,创建对象,动态调用对象的属性和方法,(通过反射机制通过类的地址加载出任何类的信息)这种使用类的方式称为反向使用类,这种机制就叫做反射。
之前也接触过这样的反射机制
xml配置中的通过访问地址来获取类对象
resultType="com.****.***.***.类名"
jdbc中的
class.forName("com.mysql.cj.jdbc.Driver");
类名
Class clazz=User.class;
反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
反射就是把java类中的各种成分映射成一个个的Java对象
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)
API中给出的class(类)的解释
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-odWV7INf-1657943770793)(D:\反射\QQ截图20220716103032.png)]
2.反射的作用
通过反射可以使程序代码访问到JVM中的类的内部信息
- 获取已经装载类的属性信息
- 获取已经装载的类的方法
- 获取已经装载的类的构造方法
3.反射的使用
1、获取Class对象的三种方式
1.1 Object ——> getClass();
1.2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
1.3 通过Class类的静态方法:forName(String className)(常用)
package com.ffyc.mybatisdemo.reflectDemo;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
User user = new User();//正向的使用类
/*
* 反射的根基是能拿到类的class对象
* */
Class clazz1=new User().getClass();//通过getClass()方法得到该对象类Class后,可以通过Class获取这个类中的相关属性和方法;
Class clazz2=User.class;
Class clazz3=Class.forName("com.ffyc.mybatisdemo.reflectDemo.User");
System.out.println(clazz1==clazz2);//拿到的都是同一个User对象
System.out.println(clazz1==clazz3);
}
}
2.通过反射获取构造方法
2.1,获得共有的构造方法
//得到无参构造(公有的)
Constructor constructor = clazz.getConstructor();
//得到有参构造(共有的)
Constructor constructor = clazz.getConstructor(int.class, String.class);
//调用构造方法
Object obj = constructor.newInstance();
2.2,获得私有的构造方法
//获得私有的构造方法
Constructor constructor = clazz.getDeclaredConstructor();
//得到所有的构造方法
Constructor[] conArray = clazz.getDeclaredConstructors(int.class, String.class);
constructor.setAccessible(true);//设置私有属性操作权(暴力操作),会破坏java的封装结构不建议使用
Object obj = constructor.newInstance(1,"admin");
3.获得成员变量并调用
/* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*/
public class Fields {
public static void main(String[] args) throws Exception {
//1.获取Class对象
Class stuClass = Class.forName("com.ffyc.mybatisdemo.reflectDemo.User");
//2.获取字段
System.out.println("************获取所有公有的字段********************");
Field[] fieldArray = stuClass.getFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
fieldArray = stuClass.getDeclaredFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("*************获取公有字段**并调用***********************************");
Field f = stuClass.getField("name");
System.out.println(f);
}
}
4.获得成员方法并调用
/* 获取成员方法并调用:
*
* 1.批量的:
* public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
* public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
* 2.获取单个的:
* public Method getMethod(String name,Class<?>... parameterTypes):
* 参数:
* name : 方法名;
* Class ... : 形参的Class类型对象
* public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
*
* 调用方法:
* Method --> public Object invoke(Object obj,Object... args):
* 参数说明:
* obj : 要调用方法的对象;
* args:调用方式时所传递的实参;
*/
public class MethodClass {
public static void main(String[] args) throws Exception {
//1.获取Class对象
Class stuClass = Class.forName("com.ffyc.mybatisdemo.reflectDemo.User");
//2.获取所有公有方法
System.out.println("***************获取所有的”公有“方法*******************");
stuClass.getMethods();
Method[] methodArray = stuClass.getMethods();
for(Method m : methodArray){
System.out.println(m);
}
System.out.println("***************获取所有的方法,包括私有的*******************");
methodArray = stuClass.getDeclaredMethods();
for(Method m : methodArray){
System.out.println(m);
}
//在已知方法名的条件下获取get方法
System.out.println("***************获取get()方法*******************");
Method getId = aClass.getMethod("getId");//在知道方法名的条件下
System.out.println(getId);
Method[] methods = aClass.getDeclaredMethods();//获取所有的方法
for(Method method:methods){
System.out.println(method);
}
//在不知道方法名的条件下获得get,set方法
Field[] fields = aClass.getDeclaredFields();
String s="{";
for(Field field:fields){
Method method = aClass.getMethod("get" + String.valueOf(field.getName().charAt(0)).toUpperCase() +
field.getName().substring(1));
Object obj=
aClass.getDeclaredConstructor(int.class,String.class).newInstance(1,"admin");
s+=field.getName()+":"+method.invoke(obj)+",";
}
s+="}";
System.out.println(s);
}
}