一、简介

上一篇文章总结了一些如何使用反射机制获取类的字段、方法以及构造方法信息的方法;本节主要总结如何通过反射动态调用类的方法、动态创建对象以及一些示例等。

二、反射使用示例

首先,本节的User类需要做一些修改,主要加入了一些静态属性以及静态方法,后面会用到,具体代码如下:

public class User {private int id;private String name;private int age;/*** 静态属性*/private static String flag;/*** 静态方法** @param name* @return*/public static String sayHello(String name) {return name;}public User() {}public User(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public static String getFlag() {return flag;}public static void setFlag(String flag) {User.flag = flag;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';}
}

【a】动态调用构造方法创建对象

  • 底层调用的是无参构造方法,所以无参构造方法必须显式声明
  • clazz.newInstance() : 通过调用Class对象的newInstance()方法创建对象
  • constructor.newInstance(Object ... initargs) : 通过调用constructor的newInstance()方法创建对象
/*** @Description: 动态调用构造方法* @author: weishihuai* @Date: 2018/12/19 16:00*/
public class DynamicInvokeConstructor {public static void main(String[] args) {Class<?> clazz;try {clazz = Class.forName("com.wsh.reflection03.User");/*** 动态调用构造方法创建对象:* 1. 底层调用的是无参构造方法,所以无参构造方法必须显式声明* 2. clazz.newInstance() : 通过调用Class对象的newInstance()方法创建对象* 3. constructor.newInstance(Object ... initargs) : 通过调用constructor的newInstance()方法创建对象*/User user = (User) clazz.newInstance();System.out.println(user);Constructor constructor = clazz.getDeclaredConstructor(int.class, String.class, int.class);User user1 = (User) constructor.newInstance(1, "zhangsan", 20);System.out.println(user1);} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {e.printStackTrace();}}
}

注意: 无参构造方法必须要显式声明,否则会报错:

【b】动态调用普通方法/静态方法

  • method.invoke(Object obj, Object... args) : obj-调用的实体对象 args:参数值

如果是调用静态方法,那么使用:

  • method.invoke(null, Object... args) : obj-null(因为静态方法不属于某个对象,属于整个类,传入null即可)  args:参数值
/*** @Description: 动态调用普通方法/静态方法* @author: weishihuai* @Date: 2018/12/19 16:00*/
public class DynamicInvokeMethod {public static void main(String[] args) {Class<?> clazz;try {//通过反射获取User类Class对象clazz = Class.forName("com.wsh.reflection03.User");/*** 通过反射操作普通方法:* method.invoke(Object obj, Object... args) : obj-调用的实体对象  args:参数值*/User user2 = (User) clazz.newInstance();Method method = clazz.getDeclaredMethod("setName", String.class);Method method1 = clazz.getDeclaredMethod("setAge", int.class);method.invoke(user2, "lisi");method1.invoke(user2, 18);System.out.println(user2);Method method2 = clazz.getDeclaredMethod("getName");method2.invoke(user2);System.out.println(user2.getName());/*** 获取静态方法*/Method staticMethod = clazz.getDeclaredMethod("sayHello", String.class);Object o = staticMethod.invoke(null, "zhangsan");System.out.println("动态调用静态方法,返回值-->" + o);} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {e.printStackTrace();}}
}

【c】动态操作字段信息

  • field.set(Object obj, Object value): field: 某个字段 obj:实体对象 value:字段值
  • field.get(Object obj): field: 某个字段 obj:实体对象

如果操作的是静态属性,那么使用:

  • field.set(null, Object value): field: 某个字段   value:字段值
  • field.get(null):    field: 某个字段
/*** @Description: 动态操作字段信息* @author: weishihuai* @Date: 2018/12/19 16:00*/
public class DynamicInvokeField {public static void main(String[] args) {Class<?> clazz = null;try {clazz = Class.forName("com.wsh.reflection03.User");/*** 通过反射API操作属性:* field.set(Object obj, Object value):    field: 某个字段   obj:实体对象   value:字段值* field.get(Object obj):   field: 某个字段  obj:实体对象*/User user3 = (User) clazz.newInstance();Field field = clazz.getDeclaredField("name");//            //不做安全检查,直接操作属性field.setAccessible(true);field.set(user3, "wangwu");
//            //wangwuSystem.out.println(user3.getName());
//            //wangwuSystem.out.println(field.get(user3));/*** 获取静态属性*/Field staticField = clazz.getDeclaredField("flag");staticField.setAccessible(true);staticField.set(null, "flag");System.out.println("静态属性flag的值为-->" + staticField.get(null));} catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException | InstantiationException e) {e.printStackTrace();}}
}

注意,不能直接访问私有属性或者私有构造方法以及私有方法,必须设置 field.setAccessible(true); 跳过安全检查才能访问私有属性、方法以及构造方法。

如果没有设置跳过安全检查直接访问的话,会直接报错,如下代码:

public class DynamicInvokeField {public static void main(String[] args) {Class<?> clazz = null;try {clazz = Class.forName("com.wsh.reflection03.User");/*** 通过反射API操作属性:* field.set(Object obj, Object value):    field: 某个字段   obj:实体对象   value:字段值* field.get(Object obj):   field: 某个字段  obj:实体对象*/User user3 = (User) clazz.newInstance();Field field = clazz.getDeclaredField("name");//            不能访问私有属性field.set(user3, "wangwu");System.out.println(user3.getName());} catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException | InstantiationException e) {e.printStackTrace();}}
}

以上就是关于如何通过反射动态操作构造方法、属性、普通方法以及静态方法,下面我们总结一些使用反射的示例:

【d】使用反射跳过泛型检查
大家都知道,泛型检查只是在编译的时候才存在的,对于编译好的Class字节码不存在泛型检查,所以我们可以利用反射获取的Class对象跳过泛型的检查。

/*** @Description: 反射示例一: 绕过泛型检查* @author: weishihuai* @Date: 2018/12/19 16:06*/
public class ReflectionExample01 {public static void main(String[] args) {List<String> namesList = new ArrayList<>();namesList.add("zhangsan");namesList.add("lisi");//        编译器报错,不满足泛型类型要求
//        namesList.add(123);System.out.println("改变之前-->" + namesList);//通过反射获取List的Class对象Class<? extends List> clazz = namesList.getClass();try {Method method = clazz.getDeclaredMethod("add", Object.class);method.invoke(namesList, 123);System.out.println("改变之后-->" + namesList);} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {e.printStackTrace();}}
}

【e】反射操作注解

我们可以通过反射,获取到类上面的注解以及字段甚至方法上面的注解,拿到这些注解的内容以及属性,可以进一步操作。下面的示例是通过反射获取注解中标注的内容信息。

自定义注解Mytable.java

@Target(ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyTable {/*** 数据表名称*/String value();
}

自定义注解MyField.java

@Target(ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyField {/*** 列名称*/String columnName();/*** 数据类型*/String type();/*** 长度*/int length();}

Student.java:

@MyTable(value = "tb_student")
public class Student {@MyField(columnName = "sname", type = "varchar2", length = 128)private String name;@MyField(columnName = "age", type = "int", length = 3)private int age;@MyField(columnName = "id", type = "int", length = 128)private int id;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

测试:

public class Demo {public static void main(String[] args) {try {//通过反射获取Student类对象Class clazz = Class.forName("com.wsh.annotation02.Student");//获取Student类的所有有效注解Annotation[] annotations = clazz.getAnnotations();for (Annotation annotation : annotations) {//@com.wsh.annotation02.MyTable(value=tb_student)System.out.println(annotation);}//获取类指定的注解MyTable myTable = (MyTable) clazz.getAnnotation(MyTable.class);System.out.println(myTable.value());  //tb_student//获取类的属性的注解Field name_field = clazz.getDeclaredField("name");MyField nameField = name_field.getAnnotation(MyField.class);System.out.println(nameField.columnName());   //snameSystem.out.println(nameField.type());  //varchar2System.out.println(nameField.length());  //128//至此,各个字段的属性名称、长度、类型都获取了、就可以动态拼接创建数据表的sql...} catch (ClassNotFoundException | NoSuchFieldException e) {e.printStackTrace();}}
}

如上图,成功获取到注解中标注的内容信息,我们进而可以进行下一步的包装处理等。

三、总结

本文是笔者对反射机制之动态操作构造方法、属性、方法的一些总结以及示例,通过两篇文章的总结,相信可以对反射有一个比较深刻的理解,并且可以掌握反射常用的一些使用方法。仅供大家参考,希望能对大家有所帮助。

Java 反射Reflection总结二相关推荐

  1. java 反射Reflection;Class类

    1.反射机制概述 java能够反射的前提:已经加载过这个类 反射可以通过类名来寻找这个类的所有相关信息.类似于人类的记忆,事先在记忆中有了这个事物的信息,人就可以通过名字来在记忆中寻找事物的具体信息. ...

  2. java反射获取方法内部_公共技术点之 Java 反射 Reflection

    本文为 Android 开源项目源码解析 公共技术点中的 Java 反射 部分 分析者:Mr.Simple,校对者:Trinea,校对状态:未完成 1. 了解 Java 中的反射 1.1 什么是 Ja ...

  3. 公共技术点之 Java 反射 Reflection

    1. 了解 Java 中的反射 1.1 什么是 Java 的反射 Java 反射是可以让我们在运行时获取类的函数.属性.父类.接口等 Class 内部信息的机制.通过反射还可以让我们在运行期实例化对象 ...

  4. java反射字段6,java反射判断字段类型

    java动态获取字段类型,深入理解 Java 虚拟机 Java内存区域与内存溢出异常,java反射判断字段类型,java动态添加字段原理 利用java反射获取泛型类的类型参数具体类对象_计算机软件及应 ...

  5. java反射机制调用带参数的方法_Java反射机制:跟着代码学反射

    1. 前言 在OOP的世界里,万物皆对象.也就是说,我们可以将任何东西抽象成一个对象. 比如人,可以抽象成一个Person类,通过new Person()来实例化一个对象:再比如鸭子,可以抽象成一个D ...

  6. 反射创建对象_如何应用Java反射技术灵活地创建程序类的对象实例

    软件项目实训及课程设计指导--如何应用Java反射技术灵活地创建程序类的对象实例 1.如何应用属性配置文件实现对系统中的配置信息进行读写操作 Java中的属性配置文件主要可以作为软件应用系统及项目的配 ...

  7. Java反射示例教程

    Java反射示例教程 Java Reflection提供检查和修改应用程序的运行时行为的能力.Java中的反射是核心java的一个先进主题.使用java反射我们可以检查一个类,在运行时接口,枚举,获取 ...

  8. 利用Java反射机制降低代码圈复杂度

    利用Java反射机制降低代码圈复杂度 在实际的工作中,我遇到了项目里老代码存在圈复杂度过高的问题,在提交代码的时候通不过CI(代码检查)的Lizard复杂度检查,所以迫切需要解决这个问题,运用Java ...

  9. Javaweb安全——Java反射

    Java反射机制 Java反射(Reflection)是Java非常重要的动态特性,通过使用反射我们不仅可以获取到任何类的成员方法(Methods).成员变量(Fields).构造方法(Constru ...

  10. Java学习之二-Java反射机制

    问题: 在运行时,对一个JAVA类,能否知道属性和方法:能否调用它的任意方法? 答案是可以的,JAVA提供一种反射机制可以实现. 目录 什么是JAVA的反射机制 JDK中提供的Reflection A ...

最新文章

  1. Matlab2013a安装简单教程以及遇到的问题解决(反复提示激活问题)
  2. python利器怎么编程-bluepy 一款python封装的BLE利器简单介绍
  3. APP多版本共存,服务端如何兼容?
  4. RuntimeError: Error occured during execution of the processing block! See the log for more info
  5. 通过阿里云容器镜像服务海外服务器构建spark-operator镜像
  6. 算法,求1亿个数的中位数
  7. Express + mongoDB + nodejs
  8. c语言中table函数,Excel的TABLE函数是什么意思?
  9. ActiveMQ的安全配置(九)
  10. 「软件项目管理」一文详解软件项目管理概述
  11. 青苹果影视系统源码v1.3.20 多功能开源影视源码
  12. django-多对多关系
  13. PBRNet:Progressive Boundary Refinement Network for Temporal Action Detection (AAAI 2020)
  14. 【Linux】解决用vi修改文件,保存文件时,提示“readonly option is set”
  15. windows下的工具链 树莓派_Lab2树莓派交叉编译(windows平台)
  16. Anaconda3安装及opencv配置
  17. 利用windrose绘制风玫瑰图并解决错误问题
  18. matlab无限长一维原子链,优·王淑华固体物理答案第三章.ppt
  19. matplotlib报错:Glyph 25151 (\N{CJK UNIFIED IDEOGRAPH-623F}) missing from current font. func(*args)
  20. 网络附加存储(NAS)

热门文章

  1. linux电脑蓝牙传输文件在哪里,Linux操作系统下操作蓝牙手机的方法 -电脑资料
  2. 极客大学架构师训练营 系统架构 消息队列 负载均衡 数据库备份 第10课 听课总结
  3. scrapy 保存html页面,28.用配合scrapy的方式爬取本地保存的html
  4. php mysqli 字段缺失,mysqli 为什么不提示字段异常
  5. 钉钉微应用怎么进入_海目星激光张荣:激光焊接在锂电池生产应用中越来越多...
  6. win10 搭建php服务器搭建,Win10平台下安装并配置php
  7. Struts2中过滤器和拦截器的区别
  8. android studio | openGL es 3.0增强现实(AR)开发 (4) 绘制简单的2D图形、显示、旋转
  9. 高斯整数、高斯素数、费马平方和定理
  10. latex在行末出现百分号的作用