反射Reflection
1:获取Class实例的三种方式
Class clazz=Person.class;
Class clazz=new person().getClass;
Class clazz=Class.forName("包名+类名");//用的最多
2:Class的实例对应加载到内存中的一个运行时类
3:创建运行时类的对象
Class clazz=Person.class;
Person p=(Person)clazz.newInstance();//必须有空参构造器,不低于private
1 /** 2 * 1:Reflection:反射:反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息, 3 * 并能直接操作任意对象的内部属性与方法 4 * 2:加载完类以后,在堆空间的方法区中就产生了一个Class类型的对象(一个类只有一个class对象) 5 * 这个对象包含了完整的类的内部信息,我们可以通过这个对象看到类的结构,称之为反射! 6 * 3:************实例化对象的区别 7 * 正常方式:导入相应的类的名称----new实例化------取得实例化对象 8 * 反射方式:实例化对象----getClass方法----得到完整的包类名称 9 * 4:反射机制提供的功能: 10 * 1在运行时判断任一对象所属的类 11 * 2在运行时改造任意一个类的对象 12 * 3在运行时判断任意一个类所具有的成员变量与方法 13 * 4在运行时获取泛型信息 14 * 5在运行时调用任意一个对象的成员变量与方法 15 * 6在运行时处理注解 16 * 7生成动态代理 17 * 18 * 5:反射相关的主要API 19 * java.lang.Class:代表一个类 20 * java.lang.reflect.Method:代表类的方法 21 * java.lang.reflect.Field:代表类的成员变量 22 * java.lang.reflect.Constructor:代表类的构造器 23 * 24 * **************************疑问?******************* 25 *1:通过直接new的方式或者反射的方式都可以创建对象,那么开发中具体用哪个:建议直接用new创建对象 26 *2:什么时候会使用反射的方式:动态性 27 *3:反射机制与封装性是否矛盾,怎么看待? :不矛盾,封装时私有化不建议你直接调用, 28 * 如果真想用使用反射调用也是可以的,只是一个建议 29 * 30 * ***********Class类的理解************** 31 * 1:类的加载过程:程序在经过javac.exe命令后,会生成一个或者多个字节码文件(.class结尾) 32 * 接着我们使用java.exe命令对某个字节码文件进行解释运行相当于将字节码文件加载到内存中, 33 * 此过程称为类的加载.加载到内存中的类称为运行时类,此运行时类就作为Class的一个实例 34 * 2:换句话说,Class的实例就对应着一个运行时类 35 * 3:加载到内存中的运行时类会缓存一定时间,在此时间之内,我们可以通过不同方式来获取此运行时类 36 * *****哪些类型可以有Class对象****** 37 * 1:class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类 38 * 2:interface:接口 3:数组 4:枚举enum 5:注解annotation 6:primitive tape;基本数据类型 39 * 7:void 40 * 41 // */ 42 public class ReflectionTest { 43 @Test 44 public void test(){ 45 //*******不使用反射 46 //1创建Person类对象: 47 Person person=new Person("hpp",23); 48 System.out.println(person); 49 person.setAge(50); 50 System.out.println(person.age); 51 //在Person类外部不可以通过对象调用私有的结构,属性,方法,构造器等等 52 } 53 @Test 54 public void test2()throws NoSuchMethodException { 55 //***********使用反射 56 Class clazz=Person.class; 57 Constructor constructor=clazz.getConstructor(String.class,int.class); 58 59 } 60 61 /** 62 * 获取Class实例的4种方式:前3种需要掌握,第三种方式使用最多 63 * 64 */ 65 @Test 66 public void test3()throws ClassNotFoundException{ 67 //方式1:调用运行时类的属性.class 68 Class clazz1=Person.class; 69 System.out.println(clazz1); 70 //方式2:通过运行时类的对象,调用getClass方法 71 Person person=new Person(); 72 Class clazz2=person.getClass(); 73 System.out.println(clazz2); 74 //方式3:通过调用Class的静态方法forName(String classPath)包名+类名 75 Class clazz3=Class.forName("Reflection.Person"); 76 System.out.println(clazz3); 77 //方式4:使用类的加载器,classLoader了解即可 78 } 79 @Test 80 public void test4(){ 81 //Class 82 Class c1=Object.class; 83 Class c2=int[].class; 84 Class c6=int[][].class; 85 Class c3=void.class; 86 Class c4=int.class; 87 Class c5=String.class; 88 System.out.println(c2==c6);//元素类型与维度一致就是同一个Class,对于数组里面的长度没关系 89 } 90 /** 91 * 二:创建运行时类的对象 92 * 93 */ 94 @Test 95 public void test5()throws Exception{ 96 Class<Person> clazz=Person.class;//首先创建Class的实例 97 Object obj=clazz.newInstance();//其次创建运行时类的对象,通过调用newInstance方法会返回一个实例, 98 //newInstance方法调用了运行时类的空参构造器, 99 //换句话说,要想使用此方法,1:必须要有空参构造器,2:构造器访问权限不能低于等于private,通常设置为public 100 Person person=(Person) obj;//记得进行强转 101 Person per=(Person)clazz.newInstance();//缩成一行 102 System.out.println(per); 103 } 104 @Test 105 public void test6(){ 106 for (int i = 0; i < 100; i++) { 107 String classpath=""; 108 int num= new Random().nextInt(3); 109 switch (num){ 110 case 0: 111 classpath="java.util.Date"; 112 break; 113 case 1: 114 classpath="java.lang.Object"; 115 break; 116 case 2: 117 classpath="Reflection.Person"; 118 break; 119 } 120 try { 121 Object obj=getInstance(classpath); 122 System.out.println(obj); 123 System.out.println("************"); 124 } catch (Exception e) { 125 e.printStackTrace(); 126 } 127 } 128 } 129 public Object getInstance(String str)throws Exception{ 130 //对于输入的字符串创建相应的对象 131 Class clazz=Class.forName(str); 132 return clazz.newInstance(); 133 } 134 /** 135 * 获取当前运行时类的属性结构 136 * 137 * 138 */ 139 @Test 140 public void test7()throws Exception { 141 //Class clazz=Class.forName("包名"); 142 Class clazz1=Person.class; 143 Class clazz2=new Person().getClass(); 144 System.out.println(clazz2); 145 146 147 } 148 /** 149 * 获取当前运行时类中的方法结构 150 */ 151 @Test 152 public void test8(){ 153 Class clazz=Person.class; 154 System.out.println(clazz.getPackage());//获取包名 155 System.out.println(clazz.getConstructors());//获取构造器 156 //getMethods():获取当前运行时类及其所有父类中声明为public权限的方法 157 Method[] methods=clazz.getMethods(); 158 //getDeclareMethods():获取当前运行时类里声明的所有方法(不包含父类) 159 Method[] demethods=clazz.getDeclaredMethods(); 160 for (Method m:methods){ 161 System.out.println(m); 162 } 163 for (Method m1:demethods){ 164 System.out.println("*****"); 165 System.out.println(m1); 166 } 167 } 168 /** 169 * 获取运行时类的方法的内部结构:了解就行 170 * 权限修饰符 返回值类型 方法名(参数类型 参数名){} 171 */ 172 /** 173 * 调用运行时类的指定的结构:属性,方法,构造器:方法最重要 174 * 175 */ 176 @Test 177 //如何调用运行时类里的指定属性,需要掌握 178 public void test9()throws Exception{ 179 Class<Person> clazz=Person.class; 180 //创建运行时类对象 181 Person p=clazz.newInstance(); 182 Person p1=clazz.newInstance(); 183 //getDeclareFiled(String fieldName):获取运行时类中指定变量名的属性 184 Field name=clazz.getDeclaredField("name"); 185 name.setAccessible(true);//保证当前属性可以访问,否则在private条件下无法访问修改 186 name.set(p,"Tom"); 187 p.setName("hello"); 188 System.out.println(p.getName()); 189 } 190 /** 191 * 如何调用运行时类的指定方法:掌握 192 */ 193 @Test 194 public void test10()throws Exception{ 195 //创建class实例 196 Class<Person> clazz=Person.class; 197 //创建运行时类对象 198 Person p=clazz.newInstance(); 199 //1:获取指定的某个方法getDeclaredMethod(),参数1:指明获取的方法名称,参数2:指明获取的方法的形参列表 200 Method method=clazz.getDeclaredMethod("showNation", String.class); 201 //2:setAccessible可访问修改调用 202 method.setAccessible(true); 203 //3:invoke():参数1:方法调用者,参数2:给方法形参赋值的实参 204 method.invoke(p,"CHN"); 205 } 206 207 208 }
浙公网安备 33010602011771号