java 反射运用
一,获取私有的属性,方法,构造器(俗名:暴力反射)
现有一个类,属性,方法,构造器均为私有的,如何创建实例对象,更该属性值,调用方法?
- public class Student {
- private String name;
- private int age;
- private Student() {
- System.out.println("调用了Student()无参私有构造器");
- }
- private String info() {
- System.out.println("调用了info()无参私有方法");
- return "Student [name=" + name + ", age=" + age + "]";
- }
- private void look(String str) {
- System.out.println("调用了look(String str)参数为String类型的私有方法,参数为:"+str);
- }
- }
main方法:
首先要创建Student类的实例对象,即调用该类私有的构造方法
- public static void main(String[] args) {
- try {
- //1.首先要创建Student类的实例对象
- //1.1创建Student类的反射对象
- Class<Student> clazz = Student.class;
- //1.2获取私有构造器
- Constructor<Student> c0 = clazz.getDeclaredConstructor();
- //1.3设置访问权限
- c0.setAccessible(true);
- //1.4创建实例对象
- Student student = c0.newInstance();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
运行,控制台输出结果:
- 调用了Student()无参私有构造器
证明调用了Student类的构造器,并创建了该类的一个实例对象
更改,获取该类的私有属性
- public static void main(String[] args) {
- try {
- //1.首先要创建Student类的实例对象
- //1.1创建Student类的反射对象
- Class<Student> clazz = Student.class;
- //1.2获取私有构造器
- Constructor<Student> c0 = clazz.getDeclaredConstructor();
- //1.3设置访问权限
- c0.setAccessible(true);
- //1.4创建实例对象
- Student student = c0.newInstance();
- //获取私有属性 name
- Field name = clazz.getDeclaredField("name");
- //设置访问权限
- name.setAccessible(true);
- //为该对象的该属性赋值
- name.set(student, "张三");
- Field age = clazz.getDeclaredField("age");
- age.setAccessible(true);
- age.set(student, 18);
- //获取该属性的值:get(实例对象)
- Object nameVal = name.get(student);
- System.out.println("name:"+nameVal);
- Object ageVal = age.get(student);
- System.out.println("age:"+ageVal);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
运行结果:
- 调用了Student()无参私有构造器
- name:张三
- age:18
调用私有方法
- public static void main(String[] args) {
- try {
- //1.首先要创建Student类的实例对象
- //1.1创建Student类的反射对象
- Class<Student> clazz = Student.class;
- //1.2获取私有构造器
- Constructor<Student> c0 = clazz.getDeclaredConstructor();
- //1.3设置访问权限
- c0.setAccessible(true);
- //1.4创建实例对象
- Student student = c0.newInstance();
- //获取私有属性 name
- Field name = clazz.getDeclaredField("name");
- //设置访问权限
- name.setAccessible(true);
- //为该对象的该属性赋值
- name.set(student, "张三");
- Field age = clazz.getDeclaredField("age");
- age.setAccessible(true);
- age.set(student, 18);
- //获取该属性的值:get(实例对象)
- Object nameVal = name.get(student);
- System.out.println("name:"+nameVal);
- Object ageVal = age.get(student);
- System.out.println("age:"+ageVal);
- //获取info方法
- Method infoMethod = clazz.getDeclaredMethod("info");
- //设置访问权限
- infoMethod.setAccessible(true);
- //执行该方法,获取返回值
- Object infoRet = infoMethod.invoke(student);
- //打印返回值
- System.out.println(infoRet);
- //获取look方法
- Method lookMethod = clazz.getDeclaredMethod("look", String.class);
- //设置访问权限
- lookMethod.setAccessible(true);
- //执行该方法,传参
- lookMethod.invoke(student, "Hello World");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
运行结果:
- 调用了Student()无参私有构造器
- name:张三
- age:18
- 调用了info()无参私有方法
- Student [name=张三, age=18]
- 调用了look(String str)参数为String类型的私有方法,参数为:Hello World
小结:通过java反射机制,可以调用任意类中的任意修饰符的属性,方法,构造器
java的反射机制跟封装冲突吗?
一个房子,没有门,没有窗户,但我为了进去,只能穿墙了...
二,通过反射机制灵活调用(多态)
先上一组简单代码
- public interface Father {
- void look();
- String see(String str);
- }
- public class AAA implements Father{
- @Override
- public void look() {
- System.out.println("this is AAA look()");
- }
- @Override
- public String see(String str) {
- System.out.println("this is AAA see()");
- System.out.println("str is " + str);
- return str;
- }
- }
- public class BBB implements Father{
- @Override
- public void look() {
- System.out.println("this is BBB look()");
- }
- @Override
- public String see(String str) {
- System.out.println("this is BBB see()");
- System.out.println("str is " + str);
- return str;
- }
- }
- public class Test01 {
- public static void main(String[] args) {
- Father a = new AAA();
- a.look();
- String seeA = a.see("Hello");
- System.out.println(seeA);
- System.out.println("==================");
- Father b = new BBB();
- b.look();
- String seeB = b.see("Hello");
- System.out.println(seeB);
- }
- }
打印结果:
- this is AAA look()
- this is AAA see()
- str is Hello
- Hello
- ==================
- this is BBB look()
- this is BBB see()
- str is Hello
当我们需要在程序运行时,有选择性的调用AAA类或BBB类
即:运行时编译,我们增加一个工厂类
- public class Factory {
- public static Father getInstance(String className) {
- if("AAA".equals(className)) {
- return new AAA();
- }else if("BBB".equals(className)) {
- return new BBB();
- }else {
- return null;
- }
- }
- }
在main方法中调用:
- public static void main(String[] args) {
- //可从外部获取(properties文件,数据库,或其他方法返回值)
- String className = "BBB";
- Father a = Factory.getInstance(className);
- a.look();
- String seeA = a.see("Hello");
- System.out.println(seeA);
- }
这样,我们就可以在运行时选择性的创建对象了
这和反射有什么关系呢?
假设,需求变更,要增加一个CCC类,同样实现了Father接口,并也动态调用
需要修改的代码:
- //增加一个CCC类,实现Father接口
- public class CCC implements Father{
- @Override
- public void look() {
- System.out.println("this is CCC look()");
- }
- @Override
- public String see(String str) {
- System.out.println("this is CCC see()");
- System.out.println("str is " + str);
- return str;
- }
- }
- //修改Factory工厂类,增加CCC类的创建方法
- public class Factory {
- public static Father getInstance(String className) {
- if("AAA".equals(className)) {
- return new AAA();
- }else if("BBB".equals(className)) {
- return new BBB();
- }else if("CCC".equals(className)){
- return new CCC();
- }else {
- return null;
- }
- }
- }
注意:在实际项目中,修改一个已经运行成功没问题的方法,是存在风险的,改完万一出错了呢...(程序员都懂...)
所以,在这里如果使用反射机制,就更加灵活,以下代码举例说明
- public class Factory {
- public static Father getInstance(String className) {
- Father f = null;
- // if("AAA".equals(className)) {
- // return new AAA();
- // }else if("BBB".equals(className)) {
- // return new BBB();
- // }else if("CCC".equals(className)){
- // return new CCC();
- // }else {
- // return null;
- // }
- try {
- f = (Father)Class.forName(className).newInstance();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return f;
- }
- }
- public class Test01 {
- public static void main(String[] args) {
- //可从外部获取(properties文件,数据库,或其他方法返回值)
- String className = "com.dream.springboot.test.clazzTest.BBB";
- Father f = Factory.getInstance(className);
- f.look();
- String see = f.see("Hello");
- System.out.println(see);
- }
- }
在Factory工厂类中,使用全类名获取实例,这样避免了增加类时就修改Factory类中的方法,可减少错误,也减少工作量
总结:反射就是当詹姆斯·高斯林给你关了一扇门,又给你打开的一扇窗
代码上传地址:https://download.csdn.net/download/lijian0420/10803158
java 反射运用的更多相关文章
- 第28章 java反射机制
java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...
- Java反射机制
Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射: 静态编译:在编译时确定类型,绑定对象,即通过 ...
- java反射(基础了解)
package cn.itcast_01; /** *Person类 */ public class Person { /** 姓名 */ private String name; ...
- java基础知识(十一)java反射机制(上)
java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...
- java基础知识(十一)java反射机制(下)
1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...
- java反射学习之二万能EXCEL导出
一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...
- java反射学习之一反射机制概述
一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...
- java反射 之 反射基础
一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...
- java反射 cglib asm相关资料
有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...
- 超详细的java反射教程
看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...
随机推荐
- 33. Extjs中的tree节点的操作
转自:https://blog.csdn.net/masterShaw/article/details/51354351?utm_source=blogkpcl9 ext 树节点操作 tree ...
- 栗染-Not enough physical memory is available to power on this virtual machine with its configured settings.
这是在打开虚拟机的时候报的错 解决办法:打开虚拟机的时候选择以管理员身份运行()目测可以 原文参考来自:http://blog.csdn.net/qq_35757415/article/details ...
- ACM_四数之和
四数之和 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有n个不同的整数,判断能否从中选4次,4个数和刚好为m.数字可重复选取. ...
- Android 性能优化(15)网络优化( 11)Manipulating Broadcast Receivers On Demand
Manipulating Broadcast Receivers On Demand This lesson teaches you to Toggle and Cascade State Chang ...
- 通信协议------Http、TCP、UDP
CP HTTP UDP: 都是通信协议,也就是通信时所遵守的规则,只有双方按照这个规则“说话”,对方才能理解或为之服务. TCP HTTP UDP三者的关系: TCP/IP是个协议组, ...
- WordPress腾讯云存储搭建教程,完美解决
写在前面的话: 为什么会有今天的话题:WordPress+腾讯云存储? 因为博主不想使用七牛云,也不想使用又拍云,所以才有了今天的话题. 在使用腾讯云存储的过程中是很不顺利的,万幸的是现在终于完美融合 ...
- Js变量类型
值类型和引用类型 值类型(基本类型):5种,Number String Boolean null undefined var a=10; var b=a; a=2; console.log(b); a ...
- git reset作用
git reset: 1. 文件从暂存区回退到工作区,撤销add 2. 版本回退 一:文件从暂存区回退到工作区,撤销add 如果想取消某个add的文件,可以使用该命令来进行撤销操作 撤消add:gi ...
- C#.NET,技巧篇(DataGridView线程操作)
这个系列的文章,主要是平时做C#.NET(Framework 3.5)开发的时候,积累的经验和技巧.我们平时总有这样的体会,遇到一个特别难解决的问题,网上寻它千百度也没能搜索到有用的信息.这时你肯定会 ...
- Windows Socket五种I/O模型——代码全攻略(转)
Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操 ...