# wft-reflect **Repository Path**: wft740/wft-reflect ## Basic Information - **Project Name**: wft-reflect - **Description**: Java反射 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2022-04-10 - **Last Updated**: 2022-04-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 反射 ## 通过实例体会反射的好处 > 支付 * 提取支付接口 ```java public interface IPayService { void pay(); } ``` * AliPay 实现具体的支付 ```java public class AliPayServiceImpl implements IPayService { public void pay() { System.out.println("您正在使支付宝支付"); } } ``` * WechaPay 实现具体的支付 ```java public class WechatPayServiceImpl implements IPayService { public void pay() { System.out.println("您正在使用微信支付"); } } ``` 测试具体的支付: > 使用场景1:根据不同的支付类型直接new对应的支付实现类 ```java public void testPayV1() { String payType = "支付宝"; if ("支付宝".equals(payType)) { new AliPayServiceImpl().pay(); } else if ("微信".equals(payType)) { new WechatPayServiceImpl().pay(); } } ``` > 使用场景2:把具体的支付模块提取出支付的具体的方法 ```java public void testPayV2() { String payType = "支付宝"; if ("支付宝".equals(payType)) { pay(new AliPayServiceImpl()); } else if ("微信".equals(payType)) { pay(new WechatPayServiceImpl()); } } public void pay(AliPayServiceImpl aliPay) { aliPay.pay(); } public void pay(WechatPayServiceImpl wechatPay) { wechatPay.pay(); } ``` > 使用场景3:场景2的升级版,使用多态 ```java public void testPayV2() { String payType = "支付宝"; if ("支付宝".equals(payType)) { pay(new AliPayServiceImpl()); } else if ("微信".equals(payType)) { pay(new WechatPayServiceImpl()); } } public void pay(IPayService payService) { payService.pay(); } ``` > 使用场景4:反射 ```java public void testPayV4() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { String payType = "com.wft.reflect.test01.service.impl.AliPayServiceImpl"; Class clazz = Class.forName(payType); Object obj = clazz.newInstance(); Method payMethod = clazz.getMethod("pay"); payMethod.invoke(obj); } ``` ## 通过概念再体会反射 Java反射机子是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用他的任意方法和属性;这种动态获取信息以及动态调动对象方法的功能成为Java语言的反射机制。 在编译后产生字节码文件的时候,类加载器子系统通过二进制字节流,负责从文件系统加载class文件。 在执行程序的时候,将字节码文件读取JVM中,这个过程叫类的加载。然后在内存中对应创建一个java.lang.Class对象,这个对象会被放入字节码信息中,这个Class对象就对应加载那个字节码信息,这个对象将被作为程序访问方法区中的这个类的各种数据的外部接口 所以,我们可以通过对象看到类的结果,这个对象就好像是一面镜子,透过镜子看到类的各种信息,我们形象的称为反射。 说明:在运行期间,如果我们要产生某个类的对象,Java虚拟机会检查该类型的Class对象是否已被加载。 如果没有加载,JVM会根据类的名称找到class文件并加载它,一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有的对象。 ## Class类的理解 ![图片](image/class.png) ## 获取字节码信息的四种方式 ```java // 方式1 Class c1 = Student.class; // 方式2 Student studnet = new Student(1, "read", "fish"); Class c2 = studnet.getClass(); System.out.println(c1 == c2); // 方式3 Class c3 = Class.forName("com.wft.reflect.test02.domain.Student"); System.out.println(c1 == c3); // 方式4: ClassLoader loader = TestGetClassType.class.getClassLoader(); Class c4 = loader.loadClass("com.wft.reflect.test02.domain.Student"); System.out.println(c1 == c4); ``` ## 可以作为Class类的实例的种类 Class类的具体的实例(可以用Class接受的): * 类: Person.class * 接口: Comparable.class * 注解: Override.class * 数组: int[] arr = {1,2,3}; arr.getClass(); * 基本的数据类型: int.class * void: void.class8 ## 获取运行时类的完整结构 ### 构造器 * 获取构造器 ```java @Test public void test01() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class clazz = Student.class; /** * 获取当前运行类public修饰的构造器 */ Constructor[] c1 = clazz.getConstructors(); for (Constructor c : c1) { System.out.println(c); } System.out.println("*************************"); /** * 获取当前运行时类所有修饰符的构造器 */ Constructor[] c2 = clazz.getDeclaredConstructors(); for (Constructor c : c2) { System.out.println(c); } System.out.println("*************************"); /** * 获取指定参数的,并且的public修复的构造器 */ Constructor c3 = clazz.getConstructor(Integer.class,String.class,String.class); System.out.println(c3); System.out.println("*************************"); /** * 获取无参构造函数,无所谓修饰符 */ Constructor c4 = clazz.getDeclaredConstructor(); System.out.println(c4); System.out.println("*************************"); } } ``` * 使用构造器(创建对象) ```java @Test public void test02() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class clazz = Student.class; Constructor constructor = clazz.getConstructor(Integer.class,String.class,String.class); /** * new实例 */ Student student = constructor.newInstance(1, "code", "coder"); System.out.println(student); System.out.println("*************************"); Constructor c2 = clazz.getDeclaredConstructor(); /** * 由于修饰符的问题可能会报错:Class com.wft.reflect.Test03Constructor can not access a member of class com.wft.reflect.test02.domain.Student with modifiers "private" */ // Student student2 = c2.newInstance(); // System.out.println(student2); c2.setAccessible(true); Student student2 = c2.newInstance(); System.out.println(student2); } ``` ### 属性 *获取属性 ```java /** * 获取属性 */ @Test public void test() throws NoSuchFieldException { Class clazz = Student.class; /** * 获取当前运行时类的所有的public修饰的属性,包括父类中的public属性 */ Field[] f1 = clazz.getFields(); for (Field field : f1) { System.out.println(field); } System.out.println("****************************"); /** * 获取当前运行时类的所有修饰符的属性(不包括父类的属性) */ Field[] f2 = clazz.getDeclaredFields(); for (Field field : f2) { System.out.println(field); } System.out.println("****************************"); /** * 获取指定的属性(当前运行和父类中public修饰的属性) */ // 当前类的属性 Field dream = clazz.getField("dream"); System.out.println("当前类属性:" + dream); // 父类的属性 Field name = clazz.getField("name"); System.out.println("父类属性:" + name); // // 当前类非public属性:java.lang.NoSuchFieldException: id // Field id = clazz.getField("id"); // System.out.println("非public属性:" + id); System.out.println("****************************"); /** * 获取当前运行类属性(所有的修饰符) */ // 获取当前类非public属性 Field id = clazz.getDeclaredField("id"); System.out.println("当前类非pulic属性:" + id); // // 获取父类属性:java.lang.NoSuchFieldException: name // Field name1 = clazz.getDeclaredField("name"); // System.out.println("父类属性:" + name1); System.out.println("****************************"); } ``` * 属性详情 ```java /** * 获取属性修饰符、类型、名称 */ @Test public void test02() throws NoSuchFieldException { Class clazz = Student.class; Field id = clazz.getDeclaredField("id"); Field name = clazz.getField("name"); /** * 获取属性的修饰符 */ int modifiers = id.getModifiers(); System.out.println("id 修饰符:" + modifiers); System.out.println("id 修饰符:" + Modifier.toString(modifiers)); int nameModifiers = name.getModifiers(); System.out.println("name 修饰符:" + nameModifiers); System.out.println("name 修饰符:" + Modifier.toString(nameModifiers)); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); /** * 获取属性的数据类型 */ Class idType = id.getType(); System.out.println("id type:" + idType); Class nameType = name.getType(); System.out.println("name type:" + nameType); /** * 获取属性的名称 */ String idName = id.getName(); System.out.println("id name:" + idName); String nameName = name.getName(); System.out.println("name name:" + nameName); } ``` * 属性操作 ```java /** * 属性操作:赋值、获取值 */ @Test public void test03() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, NoSuchFieldException { Class clazz = Student.class; Constructor constructor = clazz.getDeclaredConstructor(Integer.class, String.class, String.class); Student student = constructor.newInstance(1, "code", "coder"); System.out.println(student); Field score = clazz.getDeclaredField("score"); // java.lang.IllegalAccessException: Class com.wft.reflect.Test04Field can not access a member of class com.wft.reflect.test02.domain.Student with modifiers "" score.setAccessible(true); // 赋值 score.set(student,99); System.out.println(student); // 获取值 Object obj = score.get(student); System.out.println("score:" + obj); } } ``` ### 方法 * 获取方法 ```java @Test public void test01() throws NoSuchMethodException { Class clazz = Student.class; /** * 获取当前运行类的所有public修饰的方法(包括父类的public修饰的方法) */ Method[] methods = clazz.getMethods(); for (Method method : methods) { System.out.println(method); } System.out.println(">>>>>>>>>>>>>>>>>>>>>>>"); /** * 获取当前运行类的所有修饰符的方法 */ Method[] methods2 = clazz.getDeclaredMethods(); for (Method method : methods2) { System.out.println(method); } System.out.println(">>>>>>>>>>>>>>>>>>>>>>>"); /** * 获取当前运行类public修饰符的指定方法(包括父类public修饰符的方法) * 如果是非public修饰:java.lang.NoSuchMethodException: com.wft.reflect.test02.domain.Student.study() */ Method dance1 = clazz.getMethod("dance"); System.out.println(dance1); Method dance2 = clazz.getMethod("dance", String.class); System.out.println(dance2); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>"); /** * 获取当前运行类所有修饰符的方法(不包括父类的方法) * 如果获取父类的方法:com.wft.reflect.test02.domain.Student.eat() */ Method study = clazz.getDeclaredMethod("study"); System.out.println(study); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>"); } ``` * 方法详情 ```java @Test public void test02() throws NoSuchMethodException { Class clazz = Student.class; /** * 获取方法的具体结构: * - 修饰符 * - 返回值 * - 方法名称 * - 参数 * - 注解 * - 异常 */ System.out.println(">>>>>>>>>>>>>>>>>>>>>>>"); Method dance = clazz.getDeclaredMethod("dance", String.class); System.out.println("dance 修饰符:" + Modifier.toString(dance.getModifiers())); System.out.println("dance 返回值:" + dance.getReturnType()); System.out.println("dance 方法名:" + dance.getName()); System.out.println("dance 参数:"); Parameter[] parameters = dance.getParameters(); for (Parameter parameter : parameters) { System.out.println(parameter.getType() + " " + parameter.getName()); } System.out.println("dance 注解:"); Annotation[] annotations = dance.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } System.out.println("dance 异常:"); Class[] exceptionTypes = dance.getExceptionTypes(); for (Class exceptionType : exceptionTypes) { System.out.println(exceptionType); } System.out.println(">>>>>>>>>>>>>>>>>>>>>>>"); } ``` * 调用方法 ```java @Test public void test03() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class clazz = Student.class; Method dance = clazz.getDeclaredMethod("dance", String.class); Constructor constructor = clazz.getDeclaredConstructor(); // 不设置会抛出异常:can not access a member of class com.wft.reflect.test02.domain.Student with modifiers "private" constructor.setAccessible(true); Student student = constructor.newInstance(); System.out.println(student); dance.invoke(student,"rabbit"); } ``` ### 反射其他操作 * 获取接口 * 获取类所在的包 * 获取注解 ```java @Test public void test01() { Class clazz = Student.class; /** * 获取当前运行到了所有的接口 */ Class[] interfaces = clazz.getInterfaces(); for (Class i : interfaces) { System.out.println("当前类实现的接口:" + i); } /** * 获取当前运行类父类的接口 */ Class superclass = clazz.getSuperclass(); Class[] superclassInterfaces = superclass.getInterfaces(); for (Class superclassInterface : superclassInterfaces) { System.out.println("父类的接口:" + superclassInterface); } Package aPackage = clazz.getPackage(); System.out.println("当前类所在的包:" + aPackage); Annotation[] annotations = clazz.getAnnotations(); for (Annotation annotation : annotations) { System.out.println("当前类注解:" + annotation); } Annotation[] superclassAnnotations = superclass.getAnnotations(); for (Annotation superclassAnnotation : superclassAnnotations) { System.out.println("父类的注解:" + superclassAnnotation); } } ```