一,获取私有的属性,方法,构造器(俗名:暴力反射)

现有一个类,属性,方法,构造器均为私有的,如何创建实例对象,更该属性值,调用方法?

  1. public class Student {
  2. private String name;
  3. private int age;
  4. private Student() {
  5. System.out.println("调用了Student()无参私有构造器");
  6. }
  7. private String info() {
  8. System.out.println("调用了info()无参私有方法");
  9. return "Student [name=" + name + ", age=" + age + "]";
  10. }
  11. private void look(String str) {
  12. System.out.println("调用了look(String str)参数为String类型的私有方法,参数为:"+str);
  13. }
  14. }

main方法:

首先要创建Student类的实例对象,即调用该类私有的构造方法

  1. public static void main(String[] args) {
  2. try {
  3. //1.首先要创建Student类的实例对象
  4. //1.1创建Student类的反射对象
  5. Class<Student> clazz = Student.class;
  6. //1.2获取私有构造器
  7. Constructor<Student> c0 = clazz.getDeclaredConstructor();
  8. //1.3设置访问权限
  9. c0.setAccessible(true);
  10. //1.4创建实例对象
  11. Student student = c0.newInstance();
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. }

运行,控制台输出结果:

  1. 调用了Student()无参私有构造器

证明调用了Student类的构造器,并创建了该类的一个实例对象

更改,获取该类的私有属性

  1. public static void main(String[] args) {
  2. try {
  3. //1.首先要创建Student类的实例对象
  4. //1.1创建Student类的反射对象
  5. Class<Student> clazz = Student.class;
  6. //1.2获取私有构造器
  7. Constructor<Student> c0 = clazz.getDeclaredConstructor();
  8. //1.3设置访问权限
  9. c0.setAccessible(true);
  10. //1.4创建实例对象
  11. Student student = c0.newInstance();
  12.  
  13. //获取私有属性 name
  14. Field name = clazz.getDeclaredField("name");
  15. //设置访问权限
  16. name.setAccessible(true);
  17. //为该对象的该属性赋值
  18. name.set(student, "张三");
  19.  
  20. Field age = clazz.getDeclaredField("age");
  21. age.setAccessible(true);
  22. age.set(student, 18);
  23. //获取该属性的值:get(实例对象)
  24. Object nameVal = name.get(student);
  25. System.out.println("name:"+nameVal);
  26. Object ageVal = age.get(student);
  27. System.out.println("age:"+ageVal);
  28.  
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. }
  32. }

运行结果:

  1. 调用了Student()无参私有构造器
  2. name:张三
  3. age:18

调用私有方法

  1. public static void main(String[] args) {
  2. try {
  3. //1.首先要创建Student类的实例对象
  4. //1.1创建Student类的反射对象
  5. Class<Student> clazz = Student.class;
  6. //1.2获取私有构造器
  7. Constructor<Student> c0 = clazz.getDeclaredConstructor();
  8. //1.3设置访问权限
  9. c0.setAccessible(true);
  10. //1.4创建实例对象
  11. Student student = c0.newInstance();
  12.  
  13. //获取私有属性 name
  14. Field name = clazz.getDeclaredField("name");
  15. //设置访问权限
  16. name.setAccessible(true);
  17. //为该对象的该属性赋值
  18. name.set(student, "张三");
  19.  
  20. Field age = clazz.getDeclaredField("age");
  21. age.setAccessible(true);
  22. age.set(student, 18);
  23. //获取该属性的值:get(实例对象)
  24. Object nameVal = name.get(student);
  25. System.out.println("name:"+nameVal);
  26. Object ageVal = age.get(student);
  27. System.out.println("age:"+ageVal);
  28.  
  29. //获取info方法
  30. Method infoMethod = clazz.getDeclaredMethod("info");
  31. //设置访问权限
  32. infoMethod.setAccessible(true);
  33. //执行该方法,获取返回值
  34. Object infoRet = infoMethod.invoke(student);
  35. //打印返回值
  36. System.out.println(infoRet);
  37.  
  38. //获取look方法
  39. Method lookMethod = clazz.getDeclaredMethod("look", String.class);
  40. //设置访问权限
  41. lookMethod.setAccessible(true);
  42. //执行该方法,传参
  43. lookMethod.invoke(student, "Hello World");
  44.  
  45. } catch (Exception e) {
  46. e.printStackTrace();
  47. }
  48. }

运行结果:

  1. 调用了Student()无参私有构造器
  2. name:张三
  3. age:18
  4. 调用了info()无参私有方法
  5. Student [name=张三, age=18]
  6. 调用了look(String str)参数为String类型的私有方法,参数为:Hello World

小结:通过java反射机制,可以调用任意类中的任意修饰符的属性,方法,构造器

java的反射机制跟封装冲突吗?

一个房子,没有门,没有窗户,但我为了进去,只能穿墙了...

二,通过反射机制灵活调用(多态)

先上一组简单代码

  1. public interface Father {
  2. void look();
  3. String see(String str);
  4. }
  5. public class AAA implements Father{
  6. @Override
  7. public void look() {
  8. System.out.println("this is AAA look()");
  9. }
  10. @Override
  11. public String see(String str) {
  12. System.out.println("this is AAA see()");
  13. System.out.println("str is " + str);
  14. return str;
  15. }
  16. }
  17. public class BBB implements Father{
  18. @Override
  19. public void look() {
  20. System.out.println("this is BBB look()");
  21. }
  22. @Override
  23. public String see(String str) {
  24. System.out.println("this is BBB see()");
  25. System.out.println("str is " + str);
  26. return str;
  27. }
  28. }
  29. public class Test01 {
  30. public static void main(String[] args) {
  31. Father a = new AAA();
  32. a.look();
  33. String seeA = a.see("Hello");
  34. System.out.println(seeA);
  35. System.out.println("==================");
  36. Father b = new BBB();
  37. b.look();
  38. String seeB = b.see("Hello");
  39. System.out.println(seeB);
  40. }
  41. }

打印结果:

  1. this is AAA look()
  2. this is AAA see()
  3. str is Hello
  4. Hello
  5. ==================
  6. this is BBB look()
  7. this is BBB see()
  8. str is Hello

当我们需要在程序运行时,有选择性的调用AAA类或BBB类

即:运行时编译,我们增加一个工厂类

  1. public class Factory {
  2. public static Father getInstance(String className) {
  3. if("AAA".equals(className)) {
  4. return new AAA();
  5. }else if("BBB".equals(className)) {
  6. return new BBB();
  7. }else {
  8. return null;
  9. }
  10. }
  11. }

在main方法中调用:

  1. public static void main(String[] args) {
  2. //可从外部获取(properties文件,数据库,或其他方法返回值)
  3. String className = "BBB";
  4.  
  5. Father a = Factory.getInstance(className);
  6. a.look();
  7. String seeA = a.see("Hello");
  8. System.out.println(seeA);
  9. }

这样,我们就可以在运行时选择性的创建对象了

这和反射有什么关系呢?

假设,需求变更,要增加一个CCC类,同样实现了Father接口,并也动态调用

需要修改的代码:

  1. //增加一个CCC类,实现Father接口
  2. public class CCC implements Father{
  3. @Override
  4. public void look() {
  5. System.out.println("this is CCC look()");
  6. }
  7. @Override
  8. public String see(String str) {
  9. System.out.println("this is CCC see()");
  10. System.out.println("str is " + str);
  11. return str;
  12. }
  13. }
  14. //修改Factory工厂类,增加CCC类的创建方法
  15. public class Factory {
  16. public static Father getInstance(String className) {
  17. if("AAA".equals(className)) {
  18. return new AAA();
  19. }else if("BBB".equals(className)) {
  20. return new BBB();
  21. }else if("CCC".equals(className)){
  22. return new CCC();
  23. }else {
  24. return null;
  25. }
  26. }
  27. }

注意:在实际项目中,修改一个已经运行成功没问题的方法,是存在风险的,改完万一出错了呢...(程序员都懂...)

所以,在这里如果使用反射机制,就更加灵活,以下代码举例说明

  1. public class Factory {
  2. public static Father getInstance(String className) {
  3. Father f = null;
  4.  
  5. // if("AAA".equals(className)) {
  6. // return new AAA();
  7. // }else if("BBB".equals(className)) {
  8. // return new BBB();
  9. // }else if("CCC".equals(className)){
  10. // return new CCC();
  11. // }else {
  12. // return null;
  13. // }
  14.  
  15. try {
  16. f = (Father)Class.forName(className).newInstance();
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20.  
  21. return f;
  22. }
  23. }
  1. public class Test01 {
  2. public static void main(String[] args) {
  3. //可从外部获取(properties文件,数据库,或其他方法返回值)
  4. String className = "com.dream.springboot.test.clazzTest.BBB";
  5.  
  6. Father f = Factory.getInstance(className);
  7. f.look();
  8. String see = f.see("Hello");
  9. System.out.println(see);
  10. }
  11. }

在Factory工厂类中,使用全类名获取实例,这样避免了增加类时就修改Factory类中的方法,可减少错误,也减少工作量

总结:反射就是当詹姆斯·高斯林给你关了一扇门,又给你打开的一扇窗

代码上传地址:https://download.csdn.net/download/lijian0420/10803158

java 反射运用的更多相关文章

  1. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  2. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  3. java反射(基础了解)

    package cn.itcast_01; /** *Person类 */ public class Person {    /** 姓名 */    private String name;     ...

  4. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  5. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  6. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  7. java反射学习之一反射机制概述

    一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...

  8. java反射 之 反射基础

    一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...

  9. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

  10. 超详细的java反射教程

    看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...

随机推荐

  1. 33. Extjs中的tree节点的操作

      转自:https://blog.csdn.net/masterShaw/article/details/51354351?utm_source=blogkpcl9 ext 树节点操作   tree ...

  2. 栗染-Not enough physical memory is available to power on this virtual machine with its configured settings.

    这是在打开虚拟机的时候报的错 解决办法:打开虚拟机的时候选择以管理员身份运行()目测可以 原文参考来自:http://blog.csdn.net/qq_35757415/article/details ...

  3. ACM_四数之和

    四数之和 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有n个不同的整数,判断能否从中选4次,4个数和刚好为m.数字可重复选取. ...

  4. Android 性能优化(15)网络优化( 11)Manipulating Broadcast Receivers On Demand

    Manipulating Broadcast Receivers On Demand This lesson teaches you to Toggle and Cascade State Chang ...

  5. 通信协议------Http、TCP、UDP

    CP   HTTP   UDP: 都是通信协议,也就是通信时所遵守的规则,只有双方按照这个规则“说话”,对方才能理解或为之服务. TCP   HTTP   UDP三者的关系: TCP/IP是个协议组, ...

  6. WordPress腾讯云存储搭建教程,完美解决

    写在前面的话: 为什么会有今天的话题:WordPress+腾讯云存储? 因为博主不想使用七牛云,也不想使用又拍云,所以才有了今天的话题. 在使用腾讯云存储的过程中是很不顺利的,万幸的是现在终于完美融合 ...

  7. Js变量类型

    值类型和引用类型 值类型(基本类型):5种,Number String Boolean null undefined var a=10; var b=a; a=2; console.log(b); a ...

  8. git reset作用

    git reset: 1. 文件从暂存区回退到工作区,撤销add 2. 版本回退  一:文件从暂存区回退到工作区,撤销add 如果想取消某个add的文件,可以使用该命令来进行撤销操作 撤消add:gi ...

  9. C#.NET,技巧篇(DataGridView线程操作)

    这个系列的文章,主要是平时做C#.NET(Framework 3.5)开发的时候,积累的经验和技巧.我们平时总有这样的体会,遇到一个特别难解决的问题,网上寻它千百度也没能搜索到有用的信息.这时你肯定会 ...

  10. Windows Socket五种I/O模型——代码全攻略(转)

    Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操 ...