package Demo.java3.反射; import org.junit.jupiter.api.Test; import java.io.Serializable; import java.lang.annotation.*; import java.lang.reflect.*; import java.util.Arrays; /* 用反射是可以体现它的动态性
/* 服务器运行起来之后不知道应该new那个类的时候就用反射,体验上动态性 反射和面向对象是否冲突了 面向对象的私有化是告诉你这个方法我已经在我的类里面实现了就不需要你在调用他了, 封装性是解决到底建议你调什么样子的东西 反射是用来解决我能不能调的问题 反射可以是常用类型 int 也可以是数组(一维数组都是相同的class) 或者本身 或者void类型 接口,注解,enum枚举类型 */
*/ import static java.lang.annotation.ElementType.*; /* int i = f.getModifiers(); //输出0,1,2,3,4这样子的 //权限修饰符 String s = Modifier.toString(i); // 转换回普通的权限修饰符 public private String name = f.getName(); //返回: name,age,id //变量名称 Class type=f.getType(); //返回:class java.lang.String int int //数据类型 */ public class 反射的所有使用方法 { public static void main(String[] args) { } @Test //创建Class的三种方法 void abc_00() throws ClassNotFoundException { //方式1 Class c1=Username.class ; //找到位置 System.out.println(c1); /* class Demo.java3.反射.Username */ //方式2 Username use=new Username(); Class c2=use.getClass(); //找到当前类位置 System.out.println(c2); /* Stdio{id=1, name='张三', password='123456'} */ //方式3 Class c3 = Class.forName("class Demo.java3.反射.Username");//通过全名找到位置 System.out.println(c3); //方式四(通过类的加载器) ClassLoader loa = Username.class.getClassLoader(); //获取此类的类加载器 Class c4=loa.loadClass("class Demo.java3.反射.Username"); System.out.println(c4); } @Test //获取所有属性的类型以及修饰符 void abc_0() { Class c1=Person1.class; //返回所有自己声明的public和父类有的私有属性 Field[] fields = c1.getFields();//获取所有的public属性(继承了父类还会找父类的所有属性) for(Field f:fields) { System.out.println(f); /* 返回了所有的公有方法: public int Demo.java3.反射.Person1.id public double Demo.java3.反射.Creature.weight 返回了本类和父类的所有public属性 */ } System.out.println(); System.out.println("返回该类:"); //反回该类的所有属性包括private属性的 Field[] fields1 = c1.getDeclaredFields();//返回该类的所有属性(包括private属性的) 但不包含父类的属性 for (Field f1:fields1) { System.out.println(f1); } } @Test //权限修饰符数据类型 void abc_1() { Class clazz=Person1.class; Field[] fields = clazz.getDeclaredFields(); //返回该类的所有属性(包括private属性的) 但不包含父类的属性 for(Field f:fields) { //权限修饰符 int i = f.getModifiers(); //输出0,1,2,3,4这样子的 System.out.print(Modifier.toString(i)+" "); //转换回来成普通类型的 //private public //数据类型 Class type=f.getType(); //返回:class java.lang.String int int System.out.println(type); //class java.lang.String //变量名称 String name = f.getName(); //返回: name,age,id //变量名称 System.out.println(name);//输出他的变量名 } } @Test//获取所有方法名 void abc_2() { Class c1=Person1.class; //返回所在类及其父类的方法(public方法): // Method[] methods = c1.getMethods();//返回所在类及其父类的方法(public方法) // for (Method m:methods) // { // System.out.println(m); // } //返回所在类的方法 Method[] methods1 = c1.getDeclaredMethods();//返回所在类的方法(所有权限的方法) 和类名称 for (Method method :methods1) { System.out.println(method); /* public java.lang.String Demo.java3.反射.Person1.display(java.lang.String) private java.lang.String Demo.java3.反射.Person1.show(java.lang.String) public int Demo.java3.反射.Person1.compareTo(java.lang.String) public int Demo.java3.反射.Person1.compareTo(java.lang.Object) public void Demo.java3.反射.Person1.info() */ } } @Test // @ 注解 权限修饰符 方法名(参数类型1,形参名1) 返回值类型 void abc_3() { Class c1=Person1.class; Method[] methods = c1.getDeclaredMethods();//返回所在类的方法(所有权限的方法) //获取注解 for(Method m1:methods) { //获取方法声明的注解 Annotation[] annotations = m1.getAnnotations(); //可能会有多个注解所以用数组 for (Annotation a1:annotations) { System.out.println("获取到的注解:"+a1);//获取注解的值 /* @Demo.java3.反射.MyAnnotation(value="hello") */ } //获取所有的方法的(public private)权限修饰符加+返回值类型+方法名+形参 // private void breath() private 权限修饰符 void 返回值类型 breath 方法名 System.out.println("权限修饰符"+Modifier.toString (m1.getModifiers())+" " +"返回值类型:"+m1.getReturnType().getName()+" " +"方法名:"+m1.getName()//方法名 );//获取所有的方法的(public private)等权限修饰符 加返回值类型 方法名 //形参列表 System.out.print("("); Class[] types = m1.getParameterTypes(); //获取里面的所有返回值 if(types!=null&&types.length!=0) //不为空或者length不为0 { for (Class c:types) { System.out.print("形参:"+c.getName()); //获取他的形参 (形参:java.lang.Object) } } System.out.print(")"); /* 返回: 权限修饰符public 返回值类型:int 方法名:compareTo (形参:java.lang.String) 权限修饰符public volatile 返回值类型:int 方法名:compareTo (形参:java.lang.Object) 权限修饰符public 返回值类型:void 方法名:info () 获取到的注解:@Demo.java3.反射.MyAnnotation(value="hello") 权限修饰符private 返回值类型:java.lang.String 方法名:show (形参:java.lang.String) 权限修饰符public 返回值类型:java.lang.String 方法名:display (形参:java.lang.String) */ //抛出的异常 Class[] ex= m1.getExceptionTypes(); //获取抛出的异常 if(ex!=null&&ex.length!=0) //如果为0或者为空就是啥也没有 { for(int i=0;i<ex.length;i++) System.out.print(" "+"抛出的异常:"+ex[i].getName());//抛出异常 /* (形参:java.lang.String) 抛出的异常:java.lang.Exception */ } System.out.println();//换行一下 }//循环结束 } @Test //构造器(公有和所有的权限修饰符构造器) void abc_4() { Class c1=Person1.class; Constructor[] cs=c1.getConstructors(); //获取当前运行时类中声明为public的构造器 System.out.println("声明为public的构造器:"); for(Constructor c:cs) { System.out.println(c); //获取构造器 } System.out.println();//换行 Constructor[] cs1=c1.getDeclaredConstructors(); //获取当前运行时类中所有权限修饰符的构造器 System.out.println("所有权限修饰符的构造器:"); for(Constructor c:cs1) { System.out.println(c); //获取构造器 } /* public Demo.java3.反射.Person1() 所有权限修饰符的构造器: private Demo.java3.反射.Person1(java.lang.String,int) private Demo.java3.反射.Person1(java.lang.String) public Demo.java3.反射.Person1() */ } @Test //获取运行时的父类 void abc_5() { //获取运行时不带泛型的父类 Class c1=Person1.class; Class aClass = c1.getSuperclass(); //获取运行时的父类 System.out.println("不带泛型的父类:"+aClass); //获取运行时带泛型的父类 (会用到) Type type = c1.getGenericSuperclass();//获取运行时带泛型的父类 System.out.println("获取时带泛型的父类:"+type); //获取运行时代泛型的父类的泛型 Type type1 = c1.getGenericSuperclass();//获取运行时带泛型的父类 ParameterizedType theorized= (ParameterizedType) type1; //获取运行时代泛型的父类的泛型 Type[] Actual = theorized.getActualTypeArguments();//父类可能会有多个泛型所以是数组类型的 System.out.print("运行时代泛型的父类的泛型:"); for(Type t1:Actual) { System.out.print(t1+" "); } /* 不带泛型的父类:class Demo.java3.反射.Creature 获取时带泛型的父类:Demo.java3.反射.Creature<java.lang.String> 运行时代泛型的父类的泛型:class java.lang.String */ } @Test //获取运行时类的接口 (会用到) void abc_6() { Class cs=Person1.class; //获取运行时类的接口 Class[] interfaces = cs.getInterfaces(); //获取运行时类的接口 for (Class c1:interfaces) { System.out.println(c1); } /* interface java.lang.Comparable interface Demo.java3.反射.MyInterface */ System.out.println();//换行 //获取运行时类的父类的接口 Class[] interfaces1 = cs.getSuperclass().getInterfaces();//获取运行时类的父类的接口 for (Class c1:interfaces1) { System.out.println(c1); } /* interface java.io.Serializable */ } @Test //获取运行时类所在的包位置 void abc_7() { Class cs=Person1.class; Package aPackage = cs.getPackage();//获取运行时类所在的包位置 System.out.println("运行时所在的包位置:"+aPackage); /* 运行时所在的包位置:package Demo.java3.反射 */ } @Test //获取运行时类的注解 void abc_8() { Class cs=Person1.class; //获取运行时类的注解 Annotation[] annotations = cs.getAnnotations();//获取运行时类的注解 for(Annotation an:annotations) { System.out.println("运行时类的注解:"+an); } /* 运行时类的注解:@Demo.java3.反射. MyAnnotation(value="我是运行时类的注解") */ } //))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) //))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) //如何调用运行时类的属性,方法,构造器 @Test //获取指定的属性(因为属性一般都是用不是public类型的所有已经不使用了废弃了) /* 废弃*/ void abc_9() throws NoSuchFieldException, InstantiationException, IllegalAccessException { Class cs=Person1.class; Person1 obj = (Person1)cs.newInstance(); //获取指定的构造器 //获取指定属性要求声明为public类型的 Field ld = cs.getField("id");// 获取指定属性 ld.set(obj,12); // 获取指定构造器的属性修改属性值(相当于复制操作) int pid = (int)ld.get(obj); //获取指定对象的属性值 System.out.println(pid); //返回 : 12 } @Test //获取指定的属性 支持私有的属性 void abc_10() throws InstantiationException, IllegalAccessException, NoSuchFieldException { Class cs=Person1.class; Object instance = cs.newInstance(); //获取构造器 Field name = cs.getDeclaredField("name"); //获取属性 name.setAccessible(true); //必须得实现为true这样子才给你调用 获取设置对象的此属性值 name.set(instance,"你好"); System.out.println(name.get(instance)); //返回修改完成之后的值 } @Test //调用方法 void abc_11() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class cs=Person1.class; Object o = cs.newInstance(); //构造器调用空参构造器 Method show = cs.getDeclaredMethod("show", String.class); //输入该方法的名称,和参数 show.setAccessible(true); //保证方法是可访问私有的 Object o1 = show.invoke(o, "我是中国人"); // invok 是调用里面的方法 第一个是类构造器,第二个是参数 如果有返回值就可以接收 System.out.println(o1); /* 写的sout返回: 我的国籍是:我是中国人 返回值为:我是中国人 */ //如果方法是为静态的 Method desc = cs.getDeclaredMethod("showDesc", String.class);//声明方法 desc.setAccessible(true);//启动可以访问私有的 Object o2 = desc.invoke(Person1.class, "我爱中国");//调用方法 System.out.println(o2);//输出返回值 /* 调用; 调用了我 返回值: 我爱中国 */ } @Test //调用构造器带参数的构造器(不通用) 一般使用不带参数的因为不适合 void abc_12() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class cs=Person1.class; //1.获取指定构造器 Constructor constructor = cs.getDeclaredConstructor(String.class); //调用有参数的构造器 ,指明构造器的参数列表 //2.保证可访问 constructor.setAccessible(true);//保证能访问 //3.调用此构造器创建运行时类的对象 Person1 instance = (Person1)constructor.newInstance("我爱我的国家 传输进去构造器的值"); //调用一个参数的构造器 System.out.println(instance.toString()); /* Person1{name='我爱我的国家 传输进去构造器的值', age=0, id=0} */ } @Test // void abc_13() { Class cs=Person1.class; } } class Creature<T> implements Serializable //父类 { private char gender; public double weight; private void breath() { System.out.println("生物呼吸"); } private void eat() { System.out.println("生物吃东西 "); } } @MyAnnotation(value = "我是运行时类的注解") class Person1 extends Creature<String> implements Comparable<String>,MyInterface //主类 { //属性区 private String name; int age; public int id; //构造函数区 public Person1() { //空参构造器 } @MyAnnotation(value = "1234") private Person1(String name) { //一个参数构造器 this.name=name; } private Person1(String name,int age) { //两个参数构造器 this.name=name; this.age=age; } //方法区 private String show(String nation) //1 { System.out.println("我的国籍是:"+nation); return nation; } public String display(String interests) throws Exception //2 { return interests; } public void info() { //3 System.out.println("我是一个人"); } public int compareTo(String o) { //4 return 0; } private static String showDesc(String name) { System.out.println("调用了我"); return name; } @Override public String toString() { return "Person1{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + '}'; } } interface MyInterface //接口 { void info(); } @Target({TYPE,FIELD,METHOD, PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation{ //注解 String value() default "hello"; }