反射机制基础解析
来源:互联网 发布:ipad下载软件付费 编辑:程序博客网 时间:2024/05/22 23:27
个人博客:www.letus179.com
概念
Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
通俗来讲:反射就是把Class对象的各种成分映射成对应的Java类。
作用
java反射机制其实就是将.class
转化为.java
,也即反编译。具体主要提供了以下功能:
- 在运行时判断任意一个对象所属的
类
; - 在运行时
构造
任意一个类的对象; - 在运行时判断任意一个类所具有的
成员变量
和方法
; - 在运行时
调用
任意一个对象的方法。
后面会围绕这几点具体展开。
重要API
在java.lang.reflect
包下提供类和接口,以获得关于类和对象的反射信息。这里简单罗列了与反射相关的几个重要的API,真正想学习反射机制,除了在项目中历练,API也是非常重要的手段。英语不好理解的话,就搜搜汉化后的API文档。
具体功能实现
下面通过例子分别讲述获取Class对象的3种方式
,如何创建实例
,如何获取构造器
,如何获取方法
, 如何获取属性
以及通过反射调用方法
。
获取Class对象的3种方式
例如新建一个类MyReflectTest
,代码如下:
public class MyReflectTest {}
方式1:使用Class
类的中静态forName()
方法获得与字符串对应的Class对象
public static void main(String[] args) { try { Class<?> clz = Class.forName("test.MyReflectTest"); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
在数据库有关开发中,我们经常会用到这个方法,例如:
Class.forName("com.mysql.jdbc.Driver")
方式2: 利用对象的class
属性
public static void main(String[] args) { Class clz = MyReflectTest.class; }
注意,在基本类型和包装类型中有,例如:
Integer.TYPE
等价于
int.class
是int
的Class
对象,不等价于
Integer.class
这是Integer
的Class
对象表示,看看源码就知道了。
方式3:调用对象的getClass()
方法
public static void main(String[] args) { MyReflectTest myReflectTest = new MyReflectTest(); Class clz = myReflectTest.getClass(); }
创建实例
获取到class对象后,调用newInstance()
方法来创建Class对象对应的类实例,
测试代码:
public static void main(String[] args) throws InstantiationException, IllegalAccessException { Class clz = MyReflectTest.class; MyReflectTest newInstance = (MyReflectTest) clz.newInstance(); }
获取构造器
获取类的所有构造器,测试代码:
public static void main(String[] args) { // 获取类对象 Class clz = MyReflectTest.class; // 获取public构造器数组 Constructor[] cons = clz.getConstructors(); // 获取public,默认,protected,private构造器数组 Constructor[] declaredCons = clz.getDeclaredConstructors(); }
获取类中指定的某个构造器,测试代码:
public MyReflectTest(String name) { super(); this.name = name; } MyReflectTest(String name, int age) { super(); this.name = name; this.age = age; } public static void main(String[] args) throws NoSuchMethodException, SecurityException { // 获取类对象 Class clz = MyReflectTest.class; // 获取public构造器,构造器参数类型为String Constructor con = clz.getConstructor(String.class); // 获取public,默认,protected,private构造器,构造器参数类型为String,int Constructor declaredCon = clz.getDeclaredConstructor(String.class, int.class); }
获取方法
新增两个方法:add()
和get()
。
private void add(String name) { System.out.println(name); } public int get() { System.out.println(age); return age; }
getDeclaredMethods()
方法相关测试代码:
public static void main(String[] args) throws NoSuchMethodException, SecurityException { // 获取类对象 Class clz = MyReflectTest.class; Method[] declaredMethods = clz.getDeclaredMethods(); for (Method method : declaredMethods) { System.out.println("==============================="); // 访问修饰符 System.out.println(Modifier.toString(method.getModifiers())); // 返回类型 System.out.println(method.getReturnType()); // 方法名称 System.out.println(method.getName()); Class<?>[] parameterTypes = method.getParameterTypes(); for (Class<?> param : parameterTypes) { // 方法参数类型 System.out.println(param.getName()); } } }
执行结果:
===============================public staticvoidmain[Ljava.lang.String; //"["表示数组对象===============================privatevoidaddjava.lang.String===============================publicintget
能获取私有的方法add()
。
看看另一个反射方法:getMethods()
,代码和上面一个,基本没变化。
测试代码:
public static void main(String[] args) throws NoSuchMethodException, SecurityException { // 获取类对象 Class clz = MyReflectTest.class; Method[] methods = clz.getMethods(); for (Method method : methods) { System.out.println("+++++++++++++++++++++++++++++++++"); System.out.println(Modifier.toString(method.getModifiers())); System.out.println(method.getReturnType()); System.out.println(method.getName()); Class<?>[] parameterTypes = method.getParameterTypes(); for (Class<?> param : parameterTypes) { System.out.println(param.getName()); } } }
执行结果:
+++++++++++++++++++++++++++++++++public staticvoidmain[Ljava.lang.String;+++++++++++++++++++++++++++++++++publicintget+++++++++++++++++++++++++++++++++public finalvoidwaitlongint+++++++++++++++++++++++++++++++++public final nativevoidwaitlong+++++++++++++++++++++++++++++++++public finalvoidwait+++++++++++++++++++++++++++++++++publicbooleanequalsjava.lang.Object+++++++++++++++++++++++++++++++++publicclass java.lang.StringtoString+++++++++++++++++++++++++++++++++public nativeinthashCode+++++++++++++++++++++++++++++++++public final nativeclass java.lang.ClassgetClass+++++++++++++++++++++++++++++++++public final nativevoidnotify+++++++++++++++++++++++++++++++++public final nativevoidnotifyAll
对比上面的getDeclaredMethods()
,少了一个私有的方法add()
,但是多了好多不在本类的方法。由于每个类的超类都是Object
类,很明显,这些方法都是来自超类,看看源码也能发现这个。也就是说:
getDeclaredMethods()
获取的是本类的方法,public、默认、protected、private;getMethods()
获取的是本类和父类的所有的public的方法。
另外有获取指定某一个方法的反射方法。
测试代码:
public String save(String name, int age) { return "name: " + name + ", age: " + age; } public static void main(String[] args) throws NoSuchMethodException, SecurityException { // 获取类对象 Class clz = MyReflectTest.class; // 第一个参数是“方法名”,后面的是方法的可变参数列表 Method method = clz.getMethod("save", String.class, int.class); System.out.println(Modifier.toString(method.getModifiers())); }
执行结果:
public
其他的类似。
获取属性
创建两个成员变量name
,age
,如下:
public String name; private int age;
测试代码:
public static void main(String[] args) throws NoSuchMethodException, SecurityException { // 获取类对象 Class clz = MyReflectTest.class; Field[] fields = clz.getFields(); for (Field field : fields) { System.out.println("+++++++++++++++++++++++++"); System.out.println(Modifier.toString(field.getModifiers())); System.out.println(field.getType()); System.out.println(field.getName()); } Field[] declaredFields = clz.getDeclaredFields(); for (Field field : declaredFields) { System.out.println("========================="); System.out.println(Modifier.toString(field.getModifiers())); System.out.println(field.getType()); System.out.println(field.getName()); } }
执行结果:
+++++++++++++++++++++++++publicclass java.lang.Stringname=========================publicclass java.lang.Stringname=========================privateintage
另外getField(String)
,getDeclaredField(String)
参数为方法名,和Method
类似。
调用方法
通过上面的一系列操作获取到某一方法后,我们可以利用invoke()
方法来调用这个方法。
测试代码:
public String save(String name, int age) { return "name: " + name + ", age: " + age; } public static void main(String[] args) throws Exception { // 获取类对象 Class<MyReflectTest> clz = MyReflectTest.class; // 获取对象实例 MyReflectTest reflect = (MyReflectTest) clz.newInstance(); // 获取save方法 Method method = clz.getMethod("save", String.class, int.class); // 第一个参数为对象实例,后面的为方法的参数 Object result = method.invoke(reflect, "jack", 27); System.out.println(result); }
执行结果:
name: jack, age: 27
最后:反射在工作中其实用到的时候并不多,主要用来构建框架。譬如Spring中的IOC
也即控制反转
,其底层就是利用了反射。以后有时间再整理下这块。反射机制基础到这结束。
- 反射机制基础解析
- JAVA基础 (二)反射 深入解析反射机制
- JAVA基础 (三)反射 深入解析反射机制
- JAVA 反射机制解析
- 反射机制简单解析
- java反射机制解析
- Java反射机制解析
- java反射机制解析
- 反射机制使用解析
- java反射机制解析
- JavaSE基础:反射机制
- java反射机制基础
- .反射机制基础类
- C#反射机制基础
- java基础:反射机制
- 框架基础--反射机制
- JAVA基础--反射机制
- 【JAVA基础】反射机制
- 简单选择排序(O(n2))
- 截取IP地址
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- Reading Note: Progressive Growing of GANs for Improved Quality, Stability, and Variation
- 使用MVP注册登录模块+封装的OKhttp,拦截器+QQ第三方登录+RecyclerView+SpringView上拉加载下拉刷新网络数据
- 反射机制基础解析
- Codejam之Tidy Numbers
- 写冒泡排序可以排序多个字符串。
- HTML5使用<ruby>和<rt>来实现拼音标注效果
- 学习笔记TF064:TensorFlow Kubernetes
- Raft一致性框架_Copycat基础学习(一)
- Java互联网面试题之有XX网(互联网金融C轮企业)面试题
- 配置docker连接国内镜像库(linux)
- window下如何杀死指定端口 的进程