反射基础

类模板类,字段类,方法类,构造器

  1 package testPart1;
  2 
  3 import org.w3c.dom.ls.LSOutput;
  4 
  5 import java.io.InputStream;
  6 import java.lang.reflect.*;
  7 import java.util.Arrays;
  8 
  9 /**
 10  * 类模板类 Class<T>
 11  * Class构建T这个类型的模板
 12  * Class<T> 说明了T类型对应的类 ,T就是解剖类
 13  * Class<T>类是反射的核心
 14  *      1.通过模板处理所有类,
 15  * 获得类的模板类对象--就是类似import 导入文件的对象
 16  * 常用方法
 17  *  1.public native boolean isInstance(Object obj) 比较 模板类是否是obj的类的子类
 18  *  2.public boolean equals(Object obj) 判断是否是同一个模板类  通过各种方式创建的模板类都一样
 19  *  3.public String getName()  获得模板类的类全限定名
 20  *  4.public Field getField(String name) 只能获得public修饰的字段
 21  *  5.public Field getDeclaredField(String name) 获得任何权限修饰的字段
 22  *  6.public Method getMethod(String name, Class<?>... parameterTypes) 只能获得public修饰的方法
 23  *  7.public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获得任何权限修饰的方法
 24  * 字段类,Field
 25  *  可以处理模板类对象的对应字段
 26  *  修改,查看某个对象的字段
 27  *  相应方法
 28  *  1.解析类的字段操作
 29  *  public String getName()  获得字段名
 30  *  public Class<?> getType()  获得字段的模板类
 31  *  public int getModifiers()  获得字段修饰符的数值和,所有修饰符
 32  *  2.对象属性值相关
 33  *  public void set(Object obj, Object value)  修改obj对象的相应属性值为value
 34  *  public Object get(Object obj) 得到obj对象的相应属性值
 35  *
 36  *  Modifier类,类型
 37  *  相应方法
 38  *  public static String toString(int )
 39  *  可以将修饰符数值转为字符串
 40  *
 41  * Method类
 42  * 相应方法、
 43  * 1.解析类的方法属性
 44  * public String getName() 得到方法名
 45  * public Class<?> getReturnType() 得到方法模板类
 46  * public int getParameterCount()  得到方法参数数量
 47  * public Class<?>[] getParameterTypes()  得到方法参数类型数值
 48  * public Object invoke(Object obj, Object... args) 执行某个对象的方法
 49  *
 50  * 注意点
 51  * 权限相关
 52  * getDeclaredField
 53  * getDeclaredMethod
 54  *
 55  */
 56 
 57 public class Test1 {
 58 
 59     public static void test(){
 60         /**
 61          * 1.获取目标类型的类类型(模板类)---这是使用反射的基础
 62          * 要想使用Class<T>,首先就是将对象的类模板获得到,
 63          * 方式一 class关键字+类名获取,特点就是直接返回了确定类型,耦合度高
 64          * 方式二 forName静态方法+类的全限定名获取
 65          * 方式三 对象的getClass()方法
 66          * 考虑点 是否需要确定泛型类型,是谁在用,
 67          *      1.用户使用,就确定类型
 68          *      2.开发者最好不确定类型
 69          */
 70         Class<String> c1 = String.class;
 71         try {
 72             Class<?> c2 = Class.forName("java.lang.String");
 73         } catch (ClassNotFoundException e) {
 74             throw new RuntimeException(e);
 75         }
 76         String name = "刘";
 77         Class<?> c3 = name.getClass();
 78 
 79         /**
 80          * 2.获取目标解析类的字段
 81          * 默认获取解析类的public字段信息
 82          * getField只能获得类中是public的
 83          * 获得一个解析类的所有的字段信息
 84          */
 85         User u = new User();
 86         Class c = u.getClass();
 87         try {
 88             Field age = c.getField("age");
 89             System.out.println("字段名称:"+age.getName());
 90             System.out.println("字段类型:"+age.getType().getName());
 91             System.out.println("修饰符的值:"+age.getModifiers());
 92             System.out.println("修饰符是:"+ Modifier.toString(age.getModifiers()));
 93             User tmp = (User)c.newInstance();
 94             System.out.println("设置对象的字段值");
 95             age.set(tmp,23);
 96             System.out.println(tmp.age);
 97             System.out.println(age.get(tmp));
 98             Field[] files = c.getFields();
 99             Arrays.stream(files).forEach((f)->{
100                 System.out.println("字段名:"+f.getName()+",字段类型"+f.getType().getName()+",字段修饰符"+Modifier.toString(f.getModifiers()));
101             });
102         } catch (NoSuchFieldException e) {
103             throw new RuntimeException(e);
104         } catch (InstantiationException e) {
105             throw new RuntimeException(e);
106         } catch (IllegalAccessException e) {
107             throw new RuntimeException(e);
108         }
109         try {
110             Field name1 = c.getDeclaredField("name");
111             Field[] names = c.getDeclaredFields();
112             for (int i = 0,len = names.length;i<len;i++){
113                 System.out.println("字段修饰符:"+Modifier.toString(names[i].getModifiers())+"字段类型:"+names[i].getType().getName()+"字段名:"+names[i].getName());
114             }
115             User tmp = (User)c.newInstance();
116             System.out.println("设置对象的字段值");
117             name1.set(tmp,"张三");
118             System.out.println(tmp.name);
119             System.out.println(name1.get(tmp));
120         } catch (NoSuchFieldException e) {
121             throw new RuntimeException(e);
122         } catch (InstantiationException e) {
123             throw new RuntimeException(e);
124         } catch (IllegalAccessException e) {
125             throw new RuntimeException(e);
126         }
127     }
128     /**
129      * 易错点
130      * 1.找不到指定类异常 相应.class文件找不到,
131      * 错误代码:
132      * Class.forName("张三");   Class.forName("String");
133      * 错误原因: 参数字符串里面应该是类的全限定名(包名+类名).1不能是类名2.也不能理解是普通字符串对象
134      * 拓展,这个就相当于导包的时候import里面的值;同时需要考虑classpath正确。
135      * 2.解剖权限不足
136      * 错误代码  String.class.getField("hash"); User.class.getField("name");
137      * 错误原因: 权限不够, 1.默认只能解剖public的成员.就理解是public默认允许解剖
138      * 拓展,权限修饰符 -> 其它作用
139      * 3.修改获得字段值需要先实例化对象(本质是修改一个对象的属性值)
140      * 字段可以单独读,但是修改值是修改某个对象的相应字段值。
141      *  特殊,属于类的属性也需要通过对象修改,age.set(User,23);错误的
142      */
143 
144     /**
145      * 3.获得解析类的方法,执行对象的方法
146      */
147     public static void test2() {
148         User user = new User();
149         Class c = user.getClass();
150         try {
151 //            c.getMethod("方法名","参数类型的解析类".getClass());
152             Method info = c.getMethod("info");
153             System.out.println("名称:"+info.getName());
154             System.out.println("返回类型"+info.getReturnType().getName());
155             System.out.println("修饰符:"+Modifier.toString(info.getModifiers()));
156             System.out.println("参数数量:"+info.getParameterCount());
157 
158             //执行方法
159             //调用对象,方法参数
160             try {
161                 info.invoke(user);
162             } catch (IllegalAccessException e) {
163                 throw new RuntimeException(e);
164             } catch (InvocationTargetException e) {
165                 throw new RuntimeException(e);
166             }
167 
168             info = c.getMethod("setAge", int.class);
169             c.getDeclaredMethod("setAge",int.class);
170 //            info = c.getMethod("setAge", Integer.class);//不能这样写
171             System.out.println("名称:"+info.getName());
172             System.out.println("返回类型"+info.getReturnType().getName());
173             System.out.println("修饰符:"+Modifier.toString(info.getModifiers()));
174             System.out.println("参数数量:"+info.getParameterCount());
175             System.out.println("第一个参数类型:"+info.getParameterTypes()[0].getName());
176 
177             try {
178                 info.invoke(user,20);
179             } catch (IllegalAccessException e) {
180                 throw new RuntimeException(e);
181             } catch (InvocationTargetException e) {
182                 throw new RuntimeException(e);
183             }
184             user.info();
185         } catch (NoSuchMethodException e) {
186             throw new RuntimeException(e);
187         }
188     }
189 
190     /**
191      * 4.通过反射创建对象
192      * 获得对象的构造器对象
193      * java默认的构造方法类型
194      */
195     public static void test3() {
196         User u = new User();
197         Class c  = u.getClass();
198         Constructor con =null;
199         try {
200             con = c.getConstructor();
201         } catch (NoSuchMethodException e) {
202             throw new RuntimeException(e);
203         }
204         //获得构造方法属性
205 
206         //构造方法权限
207         System.out.println("构造方法权限为:"+Modifier.toString(con.getModifiers()));
208 
209         //打印参数类型
210         Class[] para = con.getParameterTypes();
211         if (null!=para){
212             for (int i = 0,len=para.length;i<len;i++){
213                 System.out.println(para[i].getTypeName());
214             }
215         }
216         //执行构造方法
217         try {
218             User user = (User)con.newInstance();
219             user.setAge(20);
220             System.out.println(user.getAge());
221         } catch (InstantiationException e) {
222             throw new RuntimeException(e);
223         } catch (IllegalAccessException e) {
224             throw new RuntimeException(e);
225         } catch (InvocationTargetException e) {
226             throw new RuntimeException(e);
227         }
228 
229         try {
230             con = c.getConstructor(String.class,int.class);
231         } catch (NoSuchMethodException e) {
232             throw new RuntimeException(e);
233         }
234         //获得构造方法属性
235 
236         //构造方法权限
237         System.out.println("构造方法权限为:"+Modifier.toString(con.getModifiers()));
238 
239         System.out.println("参数列表为:");
240         //打印参数类型
241         para = con.getParameterTypes();
242         if (null!=para){
243             for (int i = 0,len=para.length;i<len;i++){
244                 System.out.print(para[i].getTypeName()+",");
245             }
246         }
247     }
248     /**
249      * 5.类模板其它方法
250      */
251 
252     public static void main(String[] args) {
253         /**
254          * 类模板的路径
255          * getResource(""),得到模板类的绝对路径,其实就是.class文件的父目录--路径中可以包含包
256          * getSimpleName(),得到模板类的名字,不带包名,区别getName()获得类的全限定名
257          */
258 
259         Class u = User.class;
260         Class s = Student.class;
261         Student student = new Student();
262         User user = new User();
263         System.out.println(u.getResource(""));
264         System.out.println(u.getSimpleName());
265 
266         /**
267          * equals(Object )和isInstance(Object )方法
268          * equals用于比较两个模板类是否相等 1.实际是判断的地址2.一个类的模板类只有一个地址
269          * isInstance用于模板类和非模板类的比较, 可类比instanceof
270          * 1.判断模板类是否是对象父(爷爷,祖先)类的模板类和是对象的模板类,
271          *      反过来理解对象是否是模板类处理的类的子类,或者本身,或者孙子,或者后代。
272          * 2.可以替代 instanceof
273          *
274          */
275 
276         System.out.println(u.equals(user));//false
277         System.out.println(s.equals(student));//false
278 
279         System.out.println(u.equals(user.getClass()));//true
280         System.out.println(user.getClass().equals(u));//true
281 
282         System.out.println(u.equals(s));//false
283         System.out.println(s.equals(u));//false
284 
285         System.out.println(s.isInstance(u));//false
286         System.out.println(u.isInstance(s));//false
287 
288         System.out.println(s.isInstance(user));//false
289         System.out.println(s.isInstance(student));//true
290 
291         System.out.println(u.isInstance(user));//true
292         System.out.println(u.isInstance(student));//true
293 
294         Class o = Object.class;
295         System.out.println(o.isInstance(user));//true
296         System.out.println(o.isInstance(student));//true
297 
298         System.out.println(user instanceof User);//true
299         System.out.println(user instanceof Student);//false
300 
301         System.out.println(student instanceof Student);//true
302         System.out.println(student instanceof User);//true
303         System.out.println(student instanceof Object);//true
304     }
305 }

 2022/9/13

  反射和类构造

  通过反射可以得到类模板,在创建类模板的时候会实例化类的静态方法,初始化静态成员,执行静态代码块的代码

案例就是:注册 jdbc驱动的时候只需要写

   Class.forName("com.mysql.cj.jdbc.Driver");

然后会自动把类构造出来,就能注册驱动。

posted @ 2022-07-08 16:37  liu/564  阅读(30)  评论(0)    收藏  举报