java反射笔记
2018-09-01 05:40:33来源:博客园 阅读 ()
反射(reflect)
1. Class对象
1.1 什么是Class对象
当JVM加载某个class文件的时候,会自动创建一个唯一的Class对象(注意:由同一个类加载器加载的class文件),这个Class对象包含了整个class类的信息(例如:类的名称、访问修饰符、字段、字段描述、方法等等一切信息)。当使用new关键字创建这个类的实例时,jvm都会使用这个Class对象来创建类的实例。
1.1 获取Class对象方式
方式 | 说明 |
---|---|
Test.class | 通过类名.class直接获取 |
t1.getClass() | 通过对象的getClass()方法获取 |
Class.forName("...") | 使用Class类的forName静态方法获取,参数给的是完整类名(包名+类名) |
2. 反射
2.1 什么是反射
所谓的反射,是在程序运行时动态获得任何一个Class对象的成员信息(类信息、字段、构造方法、成员方法等),并且能在运行时依据某个Class对象创建当前类的实例。
2.2 Class常用API
方法 | 说明 |
---|---|
newInstance() | 创建类实例 |
getName() | 获取类的完整类名 |
getSimpleName() | 获取类的简单类名 |
getPackage() | 获取类对应的包信息 |
getSuperclass() | 获取父类的Class对象 |
getInterfaces() | 获取实现的所有接口 |
getClassLoader() | 获取当前类的类加载器 |
getConstructor(..) | 获取公共且明确参数类型的构造方法 |
getDeclaredConstructor(..) | 获取受保护且明确参数类型的构造方法 |
getConstructors() | 获取所有公共的构造方法 |
getDeclaredConstructors() | 获取所有(包括受保护)的构造方法 |
getField(..) | 根据字段名称获取某一个公共的字段 |
getDeclaredField(..) | 根据字段名称获取当前类某一个的字段(包括受保护的) |
getFields() | 获取所有公共的字段,包括继承自父类的公共字段 |
getDeclaredFields | 获取当前类所有字段,包括受保护的(不包括继承父类的字段) |
getMethod(..) | 根据方法名以及参数类型获取一个公共的方法 |
getDeclaredMethod(..) | 根据方法名以及参数类型获取当前类的一个受保护的方法 |
getMethods() | 获取所有公共的方法(包括继承自父类的公共方法) |
getDeclaredMethods() | 获取当前类的所有方法,包括受保护的(不包括继承父类的方法) |
isAnnotation() | 此Class是否是一个注解 |
isAnnotationPresent(..) | 当前Class时是否定义了某个注解 |
getAnnotation(..) | 获取当前类上定义的某个注解 |
getAnnotations() | 获取当前类上定义的所有注解 |
isEnum() | 此Class是否是一个枚举 |
isArray() | 此Class是否是一个数组类型 |
isInterface() | 此Class是否是一个接口 |
... | 其他API请参照官方文档 |
public class TestClass { ? public static void main(String[] args) throws Exception{ Class<?> clazz = Class.forName("edu.nf.reflect.Users"); //通过Class对象来创建实例,当前类必须提供一个公开并且无参的构造方法 Users user = (Users) clazz.newInstance(); //获取类的完整类名 System.out.println(clazz.getName()); //获取类的简单类名 System.out.println(clazz.getSimpleName()); //获取类所在的包名 System.out.println(clazz.getPackage().getName()); //获取当前类的父类的Class System.out.println(clazz.getSuperclass()); //获取当前类实现的所有接口 System.out.println(clazz.getInterfaces()); //获取加载这个类的类加载器 System.out.println(clazz.getClassLoader()); //获取公共并且参数类型为String的构造方法 clazz.getConstructor(String.class); //获取私有并且参数为int类型的构造方法 clazz.getDeclaredConstructor(Integer.TYPE); //获取所有公共的构造方法 Constructor[] consArray1 = clazz.getConstructors(); //获取所有构造方法,包括公共和是有的 Constructor[] consArray2 = clazz.getDeclaredConstructors(); //获取某一个公共的字段,参数指定字段的名字 Field f1 = clazz.getField("address"); System.out.println(f1.getName()); //获取某一个受保护的字段 Field f2 = clazz.getDeclaredField("tel"); System.out.println(f2.getName()); System.out.println("-----------------------"); //获取所有公共的字段,包括继承自父类的公共字段 Field[] fieldArray1 = clazz.getFields(); for (Field field : fieldArray1) { System.out.println(field.getName()); } System.out.println("-----------------------"); //获取所有字段,包括受保护的(不包括继承父类的字段) Field[] fieldArray2 = clazz.getDeclaredFields(); for (Field field : fieldArray2) { System.out.println(field.getName()); } System.out.println("-----------------------"); //获取某一个公共的方法(第一个参数指定方法名,第二个参数指定方法参数的类型,这是一个可变参数,有多少个参数就要指定多少个类型) Method m1 = clazz.getMethod("say", String.class); System.out.println(m1.getName()); //获取某一个受保护的方法 Method m2 = clazz.getDeclaredMethod("call"); System.out.println(m2.getName()); System.out.println("-----------------------"); //获取所有公共的方法(包括继承自父类的公共方法) Method[] methodArray1 = clazz.getMethods(); for (Method method : methodArray1) { System.out.println(method.getName()); } System.out.println("-----------------------"); //获取本类的所有方法,包括受保护的(不包括父类的方法) Method[] methodArray2 = clazz.getDeclaredMethods(); for (Method method : methodArray2) { System.out.println(method.getName()); } } } ?
2.3 Class对象中的成员
成员 | 说明 |
---|---|
Constructor | 用于描述类的构造方法 |
Field | 用于描述类的字段 |
Method | 用于描述类的方法 |
Parameter | 用于描述方法或构造方法的参数信息 |
2.3.1 Constructor常用API
API | 说明 |
---|---|
getName() | 获取当前构造方法的名称 |
getParameterCount() | 获取构造方法的参数个数 |
getDeclaringClass() | 获取声明此构造方法的Class类 |
setAccessible(..) | 设置访问开关 |
newInstance(..) | 使用当前的Constructor构建实例 |
... | 其他API请参照官方文档 |
public class TestCons { public static void main(String[] args) throws Exception{ //加载Users的class信息,并构建Class对象 Class<?> clazz = Class.forName("edu.nf.reflect.Users"); //通过class对象访问构造方法信息, // 根据构造方法的参数类型获取某一个公共的构造方法 Constructor cons1 = clazz.getConstructor(int.class); // 访问受保护的构造方法 Constructor cons2 = clazz.getDeclaredConstructor(int.class); //构造方法的名称 System.out.println(cons1.getName()); //获取构造方法的参数个数 System.out.println(cons1.getParameterCount()); //获取定义这个构造方法的Class类 System.out.println(cons1.getDeclaringClass()); //通过构造方法来创建类的实例 //由于构这个造方法是私有的,因此必须强制打开访问开关 cons1.setAccessible(true); //然后通过newInstance方法来创建类的实例,并传入构造方法所需的参数 Users user = (Users)cons1.newInstance(21); //获取所有的构造方法(包括私有和公有的) Constructor[] cons = clazz.getDeclaredConstructors(); for (Constructor con : cons) { System.out.println("参数个数: "+con.getParameterCount()); } } }
2.3.2 Field常用API
API | 说明 |
---|---|
getType() | 获取当前字段类型 |
getName() | 获取当前字段名称 |
get(..) | 获取当前字段的值 |
set(..) | 给当前字段赋值 |
setAccessible(..) | 设置访问开关 |
... | 其他API请参照官方文档 |
public class TestField { ? public static void main(String[] args) throws Exception{ Class<?> clazz = Class.forName("edu.nf.reflect.Users"); //创建类的实例 Object instance = clazz.newInstance(); //获取一个受保护的字段 Field f = clazz.getDeclaredField("tel"); //打开访问开关 f.setAccessible(true); //给字段赋值(第一个参数指定当前类的实例,第二个参数是具体的值) f.set(instance, "123456"); //取值(get方法的参数也是指定当前类的实例) System.out.println(f.get(instance)); //获取字段的类型 System.out.println(f.getType()); //获取字段的名称 System.out.println(f.getName()); } }
?
2.3.3 Method常用API
API | 说明 |
---|---|
getName() | 获取当前方法名称 |
getReturnType() | 获取当前方法的返回值 |
getParameterCount() | 获取当前方法参数的个数 |
getParameters() | 获取当前方法的参数对象 |
getParameterTypes() | 获取当前方法的所有参数类型 |
setAccessible(..) | 设置访问开关 |
invoke(..) | 回调当前的method |
... | 其他API请参照官方文档 |
public class TestMethod { ? public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("edu.nf.reflect.Users"); //构建当前类的实例 Object instance = clazz.newInstance(); //获取受保护的call方法 Method method = clazz.getDeclaredMethod("call", String.class); //获取方法的名称 System.out.println(method.getName()); //获取方法的返回值类型 System.out.println(method.getReturnType()); //获取方法参数的个数 System.out.println(method.getParameterCount()); //获取方法的所有参数对象 System.out.println(method.getParameters()); //获取方法中所有参数的类型 Class<?>[] paramsType = method.getParameterTypes(); for (Class<?> aClass : paramsType) { System.out.println(aClass); } //调用当前方法(第一个参数是当前类的实例,第二个参数开始是方法所需的参数) //invoke方法返回的是当前调用的方法的返回值 //这个方法是受保护的,因此需要先打开访问开关 method.setAccessible(true); Object returnValue = method.invoke(instance, "12345678"); System.out.println(returnValue); } } ?
2.3.4 Parameter常用API
API | 说明 |
---|---|
getType() | 获取参数类型 |
getName() | 获取参数的名称(说明:JDK8默认编译的时候是不会将参数名信息保存在字节码中,如果想要获取参数名,那么在编译时就需要加上编译参数 ,如:javac -parameters Users.java) |
... | 其他API请参照官方文档 |
?
public class TestParameter { ? public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("edu.nf.reflect.Users"); //先获取指定的受保护的方法 Method callMethod = clazz.getDeclaredMethod("call", String.class); //获取该方法的参数信息 Parameter[] params = callMethod.getParameters(); for (Parameter param : params) { //获取参数的类型 System.out.println(param.getType()); //获取参数的名称(在JDK8之前是没有办法获取参数名的,必须通过第三方字节码工具来获取) //JDK8默认编译的时候是不会讲参数名信息保存在字节码中 //如果想要获取参数名,那么在编译时就需要加上编译参数 //如:javac -parameters Users.java System.out.println(param.getName()); } } }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:spring-运行时值注入
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- 2020年java就业前景 2020-06-11
- 04.Java基础语法 2020-06-11
- Java--反射(框架设计的灵魂)案例 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash