红色标注为当前重点

反射机制概述: 动态语言的特性、通过对象查看类的内部信息 -> 运行时可调整自身结构。
反射能做的事?

java中类本身也是对象,因为所有类都是 java.lang.Class类的对象。

反射与权限修饰符疑问 ? : 反射(能不能调用的问题)、类的封装性(建不建议调用的问题)
“new或反射来实例化” 的疑问?(是否需要动态特性的问题)

反射的案例
下列文件放置于com.xj.java包下。
代码逻辑:
从test1(),test2(),test3(),test4()依次介绍Class实例创建,使用Class实例来创建目标运行时实例,体会反射的动态性,反射(Class实例)来获取任何结构信息
RejectionTest.javaPerson.javaMyInterface.javaMyAnnotation.java
RejectionTest.java
package com.xj.java;import org.junit.jupiter.api.Test;import java.lang.reflect.*;import java.util.Random;/*** @author jia* @create 2021-12-21 7:43 下午*/public class RejectionTest {@Testpublic static Class test1() throws Exception {/*** Class实例对应着一个运行时类(含void、注解、数组等任意结构),体现java万事万物皆对象。* 有4种方法获得该Class实例* */// 方法1Class clazz = Person.class;// 方法2Class clazz2 = new Person().getClass();// 方式3 全类名 (最常使用)Class clazz3 = Class.forName("com.xj.java.Person");// 方式4 类的加载器 (了解)ClassLoader classLoader = RejectionTest.class.getClassLoader();Class clazz4 = classLoader.loadClass("com.xj.java.Person");// 多种方式,其实是同一个运行时类System.out.println(clazz == clazz2);System.out.println(clazz == clazz3);System.out.println(clazz == clazz4);System.out.println(clazz3);return clazz3;}@Testpublic Person test2() throws Exception {/*** 使用反射(Class实例)来创建运行时实例。* 注意:必须提供空参构造器,一般为public权限。* */Class clazz = test1();// Person obj = (Person) clazz.newInstance();Person obj = (Person) clazz.getDeclaredConstructor().newInstance();System.out.println(obj);return obj;}@Testpublic void test3() throws Exception{/*** 体会反射的动态性* */int t = new Random().nextInt(2);String classPath = null;switch (t){case 0:classPath = "com.xj.java.Person";break;case 1:classPath = "java.lang.Object";break;}Object obj = getInstance(classPath);System.out.println(obj);}public Object getInstance(String classPath) throws Exception {Class clazz = Class.forName(classPath);// Object obj = clazz.newInstance();Object obj = clazz.getDeclaredConstructor().newInstance();return obj;}@Testpublic void test4() throws Exception{/**反射(Class实例)来获取任何类信息,包括注解等*/// Class实例Class clazz = Class.forName("com.xj.java.Person");// 获得空参构造器结构Constructor declaredConstructor = clazz.getDeclaredConstructor();// 获取构造器,一般获取空参构造器declaredConstructor.setAccessible(true);// 利用构造器结构来实例化对象Person person = (Person) declaredConstructor.newInstance();// 调用具体实例的方法Method show = clazz.getDeclaredMethod("show", String.class);// 方法名,形参列表show.setAccessible(true); // 无视权限限制Method info = clazz.getDeclaredMethod("info");// 静态方法info.setAccessible(true);Object showreturnval = show.invoke(person, "中国");// 具体实例,方法形参Object inforeturnval = info.invoke(person); // 静态方法(此处方法无形参), 方法无返回值依然要可接收返回值,则此处返回null。System.out.println("show方法返回值:" + showreturnval);System.out.println("info静态方法的空返回值:" + inforeturnval);// 修改和访问具体实例额的属性Field name = clazz.getDeclaredField("name");name.setAccessible(true);name.set(person,"good man");System.out.println("对象的name属性:" + name.get(person));// 访问注解信息MyAnnotation myAnnotation = (MyAnnotation)clazz.getDeclaredAnnotation(MyAnnotation.class);// 获取注解System.out.println("注解的value信息:" + myAnnotation.value());// 获取包结构Package pack = clazz.getPackage();System.out.println("包名:"+pack);// 获取接口结构Class[] interfaces = clazz.getInterfaces();for (Class v : interfaces){System.out.println(v);}// 获得父类Class superClazz = clazz.getSuperclass();System.out.println("父类:" +superClazz.getName());// 获得带泛型的父类Type genericSuperclass1 = clazz.getGenericSuperclass();System.out.println("带泛型的父类:" + genericSuperclass1.getTypeName());// 获取泛型信息(包括泛型类、泛型接口)Type genericSuperclass = clazz.getGenericSuperclass();ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();for (Type type : actualTypeArguments){System.out.println("类的泛型信息:" + type.getTypeName());}Type[] genericInterfaces = clazz.getGenericInterfaces();for (Type type : genericInterfaces){System.out.println("接口的泛型信息:" + type.getTypeName());}}}
国籍:中国,名字:null,年龄:0 我是静态方法 show方法返回值:中国 info静态方法的空返回值:null 对象的name属性:good man 注解的value信息:my annotation for class 包名:package com.xj.java interface java.lang.Comparable interface com.xj.java.MyInterface 父类:com.xj.java.Creater 带泛型的父类:com.xj.java.Creater
类的泛型信息:java.lang.String 接口的泛型信息:java.lang.Comparable 接口的泛型信息:com.xj.java.MyInterface
Person.java
package com.xj.java;import java.io.Serializable;/*** @author jia* @create 2021-12-21 7:42 下午*/class Creater<T> implements Serializable {private char gender;public double weight;private void breath(){System.out.println("生物呼吸");}private void eat(){System.out.println("生物进食");}}@MyAnnotation(value="my annotation for class")public class Person extends Creater<String> implements Comparable<String>,MyInterface{public String name;private int age;public Person(){};private Person(String name) {this.name = name;}public Person(String name, int age) {this.name = name;this.age = age;}@MyAnnotation(value="my annotation for show method")@Overridepublic String show(String nation){System.out.println("国籍:" + nation + ",名字:" + this.name + ",年龄:" + this.age);return nation;}@MyAnnotation(value="my annotation for info static method")private static void info(){System.out.println("我是静态方法");}@Overridepublic int compareTo(String o) {return 0;}}
MyAnnotation.java
package com.xj.java;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;/*** @author jia* @create 2021-12-22 10:49 上午*/@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})@Retention(RetentionPolicy.RUNTIME) // 持续到RUNTIMEpublic @interface MyAnnotation {String value() default "hello";}
MyInterface.java
package com.xj.java;/*** @author jia* @create 2021-12-22 10:51 上午*/public interface MyInterface {public String show(String nation);}


