Java反射剖析 我就是我 2024-02-18 17:41 20阅读 0赞 ## Java反射 ## ### 一、Annotation的原理解析 ### https://www.cnblogs.com/peida/archive/2013/04/24/3036689.html ### 二、调用构造函数 ### #### 1. 走读API #### 在Class类中提供一下的操作方法: 取得全部构造: publicConstructor<?>\[\] getConstructors() throws SecurityException 取得指定参数类型的构造: publicConstructor<T> getConstructor(类<?>...parameterTypes) throws NoSuchMethodException, SecurityException 在反射过程中是一个只认识类型不认具体对象的工具类,以上方法返回的是 java.lang.reflect.Constructor,这个类有如下方法: 取得构造方法的名称:publicString getName() 取得构造方法的修饰符:publicint getModifiers() 但是所有修饰符都是通过数字编号取得的,即如果想要取得具体的内容必须将相应的数字转为关键字,可以使用“java.lang.reflect.Modifier”类完成,这个类中提供了简单的方法使数字编号转为具体的关键字:public static String toString(int mod); #### 2. 实例代码1(获取全部,不指定参数) #### package cn.km; import java.io.ObjectStreamException; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; class Book { private String title; private Double price; public Book(String title) throwsRuntimeException, NullPointerException,ObjectStreamException { this.title = title; } public Book(String title,Double price){ this.title = title; this.price = price; } @Override public String toString() { return"书名: " + this.title + ",价格:" + this.price ; } } publicclassTestDemo { publicstaticvoid main(String[] args) throwsException{ Class<?> cls =Class.forName("cn.km.Book"); Constructor<?> cons[] = cls.getConstructors();//取得全部构造 for(inti = 0; i < cons.length; i++){ System.out.print(Modifier.toString(cons[i].getModifiers())+ " "); //获取构造函数修饰符 System.out.print(cons[i].getName()+ "("); //获取构造函数名 Class<?>params[] = cons[i].getParameterTypes(); for(intj = 0; j < params.length; j++){ System.out.print(params[j].getSimpleName()+ " arg" + j); if(j < params.length - 1){ System.out.print(", "); } } System.out.print(") "); Class<?>exp[] = cons[i].getExceptionTypes(); //取得全部异常信息 if(exp.length > 0){ System.out.print(" throws "); for(intx = 0; x < exp.length; x++){ System.out.print(exp[x].getSimpleName()); if(x < exp.length - 1){ System.out.print(" , "); } } } System.out.println(); } } } #### 3. 示例代码2(指定参数) #### package cn.km; import java.io.ObjectStreamException; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; class Book2 { privateString title; privateDouble price; Public Book2(String title,Double price)throws RuntimeException, NullPointerException,ObjectStreamException{ this.title= title; this.price= price; } @Override publicString toString() { return "书名: " + this.title + ", 价格:" + this.price ; } } public class getConstructorsWithPara { publicstatic void main(String[] args) throws Exception{ Class<?> cls =Class.forName("cn.km.Book2"); Constructor<?>cons = cls.getConstructor(String.class,Double.class); //取得指定参数构造 Book2 book2 = (Book2)cons.newInstance("java develop",79.6); System.out.println(book2); } } ### 三、调用普通函数 ### #### 1. 走读API #### 清楚了构造函数的调用之后,继续普通函数,在Class类里面提供了两组普通函数获取的方法: 第一组方法: |-public 方法\[\] getDeclaredMethods() throwsSecurityException |-public 方法 getDeclaredMethod(String name,类<?>... parameterTypes) throwsNoSuchMethodException, SecurityException 第二组方法: |-public 方法\[\] getMethods() throwsSecurityException |-public 方法 getMethod(String name,类<?>... parameterTypes) throws NoSuchMethodException, SecurityException #### 2. 实例代码3(getMethods和getDeclaredMethods比较) #### package cn.km.method; import java.lang.reflect.Method; interface Message{ publicvoid print(); } abstractclass Info{ publicabstractvoid get(); } class MessageImpl extends Info implements Message{ @Override publicvoid print() {} //覆盖接口中的方法 @Override publicvoid get() {} //继承抽象类的方法 publicvoid set() {} //定义自己的方法 } publicclass TestDemo { publicstaticvoid main(String[] args) throws ClassNotFoundException { Class<?> cls = Class.forName("cn.km.method.MessageImpl"); Method met[] = cls.getMethods(); for(inti = 0; i < met.length; i++){ System.out.println(met[i]); } System.out.println("--------------------------------------"); Method met2[] = cls.getDeclaredMethods(); for(inti = 0; i < met2.length; i++){ System.out.println(met2[i]); } } } 输出结果 ![SouthEast][] 使用getMethods获取的 使用getDeclaredMethods获取的是本类中定义的所有操作方法,与继承无关。。 以上的代码是利用了Method类之中的toString()方法取得了每一个方法的信息,现在要获取完整的方法信息, 取得方法的返回值类型:public 类<?> getReturnType() 取得方法的参数类型:public 类<?>\[\] getParameterTypes() 取得方法的异常信息:public 类<?>\[\] getExceptionTypes() #### 3. 实例代码4(获取方法的修饰符、参数类型、异常信息) #### package cn.km.method; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; interface Message{ publicvoid print(); } abstractclass Info{ publicabstractvoid get(String name,Integer age); } class MessageImpl extends Info implements Message{ @Override publicvoid print() {} //覆盖接口中的方法 @Override publicvoid get(String name,Integer age) {} //继承抽象类的方法 public String set(String name) throws Exception,NullPointerException{ returnnull; }//定义自己的方法 } publicclass TestDemo { publicstaticvoid main(String[] args) throws ClassNotFoundException { Class<?> cls = Class.forName("cn.km.method.MessageImpl"); Method met[] = cls.getDeclaredMethods(); for(inti = 0; i < met.length; i++){ System.out.print(Modifier.toString(met[i].getModifiers()) + " "); //获取方法修饰符 System.out.print(met[i].getReturnType().getSimpleName()+" "); System.out.print(met[i].getName() + " ( "); //获取参数类型 Class<?>paramTypes[] = met[i].getParameterTypes(); for(intj = 0 ; j < paramTypes.length; j++){ System.out.print(paramTypes[j].getSimpleName() + " arg" + j); if(j < paramTypes.length - 1){ System.out.print(" , "); } } System.out.print(" )"); //获取抛出的异常信息 Class<?>exceptions[] = met[i].getExceptionTypes(); if(exceptions.length > 0){ System.out.print(" throws "); for(intt = 0; t < exceptions.length; t++){ System.out.print( exceptions[t].getSimpleName() ); if(t < exceptions.length - 1){ System.out.print(" , "); } } } System.out.println(); } } } 在Method中提供了一个比较重要的方法: 调用本类的invoke方法: public Object invoke(Object obj,Object...args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException 在使用invoke方法的时候,一定要保证已经存在了本类的实例化对象,而方便的是,这个实例化对象可以是Object 可以直接利用Class类反射的实例化对象,而后通过Object类对象操作。而没有必要向下转型。。 #### 4. 实例代码5(invoke无返回值) #### package cn.km.method; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; class Message{ publicvoid echo(String str){ System.out.println(str); } } publicclass TestDemo { publicstaticvoid main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.km.method.Message"); Object object = cls.newInstance(); Method method = cls.getDeclaredMethod("echo", String.class); method.invoke(object, "nihao !"); } } #### 5. 实例代码6(invoke 有返回值) #### package cn.km.method; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; class Message{ public String echo(String str){ return"echo: " + str; } } publicclass TestDemo { publicstaticvoid main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.km.method.Message"); Object object = cls.newInstance(); Method method = cls.getDeclaredMethod("echo", String.class); String result = (String) method.invoke(object, " nihao !"); System.out.println(result); } } 在实际的代码中,简单java类之中的属性一定要进行封装、封装后的属性要按照指定的要求编写setter,getter #### 6. 实例代码7(利用反射实现getter,setter调用) #### package cn.km.method; import java.lang.reflect.Method; importcom.sun.xml.internal.ws.util.StringUtils; class Dept{ private String dname; public String getDname() { returndname; } publicvoid setDname(String dname) { this.dname = dname; } } publicclass TestDemo { publicstaticvoid main(String[] args) throws Exception { String className = "cn.km.method.Dept"; String property = "dname"; String value = "development"; Class<?> cls = Class.forName(className); //获取get方法 Method setter = cls.getDeclaredMethod("set" + StringUtils.capitalize(property), String.class); //获取set方法 Method getter = cls.getDeclaredMethod("get" + StringUtils.capitalize(property)); Object object = cls.newInstance(); //执行set方法 setter.invoke(object, value); //执行get方法 System.out.println(getter.invoke(object)); } } **上面有一个小的缺陷就是需要指定set的参数类型。。。。** ### 四、调用成员 ### 一个类中可以定义的成员:全局常量、全局变量、普通常量、普通变量,在Class类中提供了两组取得成员的方法: 第一组: public 字段\[\] getFields() throws SecurityException public 字段 getField(String name) throws NoSuchFieldException,SecurityException 第二组: public 字段\[\] getDeclaredFields() throws SecurityException public 字段 getDeclaredField(String name) throws NoSuchFieldException,SecurityException ### ### ### 五、其他 ### #### 1. StringUtils.capitalize(Stringarg0) #### 把字符串的首字母大写。如果你传入的字符串首字符本身就是大写,不作任何改变。。 [SouthEast]: https://image.dandelioncloud.cn/pgy_files/images/2024/01/29/5eb7bbed4cb647d8acad600c8c44c085.png
相关 Java反射机制深入剖析及常见误区 Java反射机制是Java语言提供的一种能力,让程序在运行状态中,可以动态地获取类的信息(如方法、属性等),并且能够调用这些方法和访问属性。 以下是反射机制的几个关键点: 痛定思痛。/ 2024年09月19日 20:21/ 0 赞/ 7 阅读
相关 Java反射机制深入剖析和应用示例 Java反射机制是Java语言内核的一部分,它提供了一种在运行时检查类、字段、方法等信息,并动态调用它们的方法。 深入剖析: 1. 类的加载:通过ClassLoader,如 分手后的思念是犯贱/ 2024年09月19日 18:48/ 0 赞/ 6 阅读
相关 错误剖析:Java反射API常见使用误区 Java反射API,它是Java语言提供的一种能力,能够让程序在运行时动态获取类的信息,并调用对象的方法。然而,在实际使用中,可能会遇到一些误区。以下是一些常见的使用误区: 素颜马尾好姑娘i/ 2024年09月18日 20:48/ 0 赞/ 4 阅读
相关 Java反射机制深入剖析:常见问题与解决策略 Java的反射机制是Java语言强大的特性之一,它允许我们在运行时检查类、方法和字段等信息。下面我们将深入剖析反射机制的常见问题及其解决策略。 1. **获取对象**:如何在 女爷i/ 2024年09月18日 10:54/ 0 赞/ 2 阅读
相关 Java反射机制深入剖析:获取类信息问题案例 在Java编程中,反射是一个强大的工具,它允许我们在运行时检查和修改对象的内部结构。然而,获取类信息并进行操作,可能会遇到一些问题。下面是一些典型的案例: 1. **不存在的 叁歲伎倆/ 2024年09月12日 05:30/ 0 赞/ 23 阅读
相关 Java反射剖析 Java反射 一、Annotation的原理解析 https://www.cnblogs.com/peida/archive/2013/04/24/3036689. 我就是我/ 2024年02月18日 17:41/ 0 赞/ 21 阅读
相关 Java反射(原理剖析与使用) 一、反射机制是什么 1、Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过clas 冷不防/ 2023年09月27日 00:29/ 0 赞/ 82 阅读
相关 Java反射机制原理剖析 作者:罗大然不写代码 链接:https://www.zhihu.com/question/24304289/answer/38218810 来源:知乎 著作权归作者 港控/mmm°/ 2022年06月05日 08:12/ 0 赞/ 198 阅读
相关 java反射-通过实例来剖析一个类 前言 上一次看java反射还是在java核心技术里面看的,当时不知道干嘛用的,现在又遇见了,再学习一次,通过实例来记录,方便以后拾遗. 原理 java反射就是将内 约定不等于承诺〃/ 2022年05月20日 03:06/ 0 赞/ 206 阅读
还没有评论,来说两句吧...