一.反射实例化对象

经过一系列的分析之后发现虽然可以获取Class类的实例化对象,但是依然觉得这个对象的获取意义不是很大,因此可以通过以下几个案例去理解反射的核心意义

--反射实例化对象:获取Class对象之后最大的意义并不是在于只是一个对象的实例化操作形式,更重要的是Class类中提供有一个对象的反射实例化方法,在JDK1.9之前的实例化:public T newInstance() throw InstantiationException,IllegalAccessException,该方法代替了new 关键字的使用,但是在JDK1.9之后则发生了变化:class.getDeclaredConstructor().newInstance();

--范例:通过newInstance()方法实例化对象

1 package反射.认识反射机制.entity;2

3 /**

4 *@author: S K Y5 *@version:0.0.16 */

7 public classPerson {8 public Person() { //任何情况下只要实例化对象则一定要调用类中的构造方法

9 System.out.println("Person对象实例化了");10 }11

12 @Override13 publicString toString() {14 return "我是一个好人";15 }16 }

1 public classDemo {2 public static void main(String[] args) throwsClassNotFoundException, IllegalAccessException, InstantiationException {3 Class> aClass = Class.forName("反射.认识反射机制.entity.Person");4 Object o = aClass.newInstance(); //实例化对象

5 System.out.println(o);6 }7 }

--运行结果

Person对象实例化了

我是一个好人

Process finished with exit code0

--现在通过反射实现的对象实例化处理,依然要调用类中的无参构造方法,其本质等价于new 关键字的使用,但是该方法在JDK1.9之后被替代了,因为默认的Class类中的newInstance()方法只能够调用无参构造,所以很多的开发者认为其描述的不准确,于是将其变换了形式(后续会说明)

二.反射与工厂设计模式

如果要想进行对象的实例化处理除了可以使用关键字new 之外,还可以挺过反射机制来完成.那么思考一个问题:为什么要提供有一个反射的实例化?到底是使用关键字new还是使用反射进行对象实例化呢?

--如果想要更好的解决此类问题,最好的解释方案就是通过工厂设计模式来解决.工厂设计模式的最大特点:客户端的程序类不直接牵扯到对象的实例化管理,只与接口发生关联,通过工厂了获取接口的实例化对象,传统的工厂设计模式:

1 interfaceMessage{2 public void send(); //消息发送

3 }4 class NetMessage implements Message{ //网络消息实现类

5 @Override6 public voidsend() {7 System.out.println("发送网络消息");8 }9 }10 public classFactoryDemo {11 public static voidmain(String[] args) {12 Message message = new NetMessage(); //如果直接实例化则一定会有耦合问题

13 }14 }

--在实际的开发中,接口的主要作用是为不同的层提供有一个操作的标准.但是此时如果直接将一个子类设置为接口实例化操作,那么一定会有耦合问题,所以使用了工厂设计模式来解决此问题.

--范例:传统的工厂设计模式

1 interfaceMessage {2 public void send(); //消息发送

3 }4

5 class NetMessage implements Message { //网络消息实现类

6 @Override7 public voidsend() {8 System.out.println("发送网络消息");9 }10 }11

12 classFactory {13 privateFactory() {14 } //没有产生实例化对象的意义

15

16 public staticMessage getInstance(String className) {17 if ("NetMessage".equals(className)) {18 return newNetMessage();19 }20 return null;21 }22 }23

24 public classFactoryDemo {25 public static voidmain(String[] args) {26 Message message = Factory.getInstance("NetMessage");27 message.send();28 }29 }

--此种工厂设计模式属于静态工厂设计模式,此时如果追加一个子类,那么工厂类就需要进行相应的修改(追加相应的判断语句),否则无法获得新的子类的实例化对象.工厂设模式最有效解决的是子类与客户端的耦合问题,但是解决的核心思想是在于提供有一个工厂类作为过渡端,可是随着项目的进行,Message接口可能会有更多的子类,而且随着时间的推移,子类会越来越多,因此工厂类永远都需要修改,并且永无停止之日.

--此时最好的解决方案就是不使用关键字new来完成对象的实例化,因为关键字new在使用的时候需要有一个明确的类存在.而newInstance()的方法只需要有一个明确表示类名称的字符串即可应用:

1 interfaceMessage {2 public void send(); //消息发送

3 }4

5 class NetMessage implements Message { //网络消息实现类

6 @Override7 public voidsend() {8 System.out.println("发送网络消息");9 }10 }11

12 classFactory {13 privateFactory() {14 } //没有产生实例化对象的意义

15

16 public static Message getInstance(String className) throwsException {17 return(Message) Class.forName(className).newInstance();18 }19 }20

21 public classFactoryDemo {22 public static void main(String[] args) throwsException {23 Message message = Factory.getInstance("反射.反射应用案例.NetMessage");24 message.send();25 }26 }

--此时如果对子类继续进行扩充的话,是没有必要修改工厂类的.利用反射机制实现的工厂设计模式,最大的优势在于,对于接口的子类的扩充,将不再影响到工厂类的定义.但是现在依然需要进行思考,在实际的项目开发之中,有可能会存在大量的接口,并且这些接口可能都需要通过工厂类来实例化对象,所以此时的工厂设计模式不应该只为一个Message接口服务,而应该变为为所有的接口服务(使用泛型实现开发需求):

1 interfaceService {2 public voidservice();3 }4

5 class HouseService implementsService {6 @Override7 public voidservice() {8 System.out.println("为您的住房提供服务.");9 }10 }11

12 interfaceMessage {13 public void send(); //消息发送

14 }15

16 class NetMessage implements Message { //网络消息实现类

17 @Override18 public voidsend() {19 System.out.println("发送网络消息");20 }21 }22

23 classFactory {24 privateFactory() {25 } //没有产生实例化对象的意义

26

27 /**

28 * 获取接口实例化对象29 *30 *@paramclassName 接口的子类31 *@paramtClass 描述的是一个接口的类型32 *@return如果子类存在则返回指定接口33 *@throwsException34 */

35 public static T getInstance(String className, Class tClass) throwsException {36 returntClass.cast(Class.forName(className).newInstance());37 }38 }39

40 public classFactoryDemo {41 public static void main(String[] args) throwsException {42 Message message = Factory.getInstance("反射.反射应用案例.NetMessage",Message.class);43 message.send();44 Service instance = Factory.getInstance("反射.反射应用案例.HouseService", Service.class);45 instance.service();46 }47 }

--此时的工厂设计模式才是所谓的高可用的工厂设计模式,而这种操作的实现依赖的就是泛型.此时的工厂设计模式将不再受限于指定的接口,可以为所有的接口提供实例化对象.

三.反射与单例设计模式

单例设计模式的核心本质在于类内部的构造方法私有化,在类的内部产生实例化对象之后在外部通过static方法获取到实例化对象进行类中的结构调用.单例设计模式一共有两种,懒汉式和饿汉式(饿汉式的单例是不再本次的讨论范围之内的,主要讨论懒汉式的单例)

--范例:观察懒汉式单例的问题

1 classSingleton {2 private static Singleton instance = null;3

4 privateSingleton() {5 }6

7 public staticSingleton getInstance() {8 if (instance == null) {9 instance = newSingleton();10 }11 returninstance;12 }13

14 public voidprint() {15 System.out.println("单例模式加载");16 }17

18 }19

20 public classLazyLoadDemo {21 public static voidmain(String[] args) {22 Singleton singleton =Singleton.getInstance();23 singleton.print();24 }25 }

--此时我们的操作是在单线程的环境下运行的,如果使用多线程

1 classSingleton {2 private static Singleton instance = null;3

4 privateSingleton() {5 System.out.println(Thread.currentThread().getName() + " 实例化单例对象");6 }7

8 public staticSingleton getInstance() {9 if (instance == null) {10 instance = newSingleton();11 }12 returninstance;13 }14

15 public voidprint() {16 System.out.println("单例模式加载");17 }18

19 }20

21 public classLazyLoadDemo {22 public static voidmain(String[] args) {23 for (int i = 0; i < 3; i++) {24 new Thread(() ->{25 Singleton.getInstance();26 }, "[单例创建者" + (i + 1) + "]").start();27 }28 }29 }

--运行结果

[单例创建者1] 实例化单例对象

[单例创建者2] 实例化单例对象

[单例创建者3] 实例化单例对象

Process finished with exit code0

--单例设计模式最大的特点是在整体运行之中,只允许产生一个实例化对象,当有了若干实例化对象之后,那么就不是单例设计模式了,我们可以大致分析单例模式的运行流程如下:

1.判断instance是否为空?

2.如果instance为空,实例化instance对象

3.返回当前的instance

--因此在多线程的设计中,每一个线程在执行步骤1的时候都会认为此时的对象为空,那么都会去创建这个对象的实例,这样一来单例设计模式也就失去了意义,如果想要解决这类问题,关键的核心就在于要解决同步处理,而解决同步处理的核心就是使用synchronized关键字

1 classSingleton {2 private static Singleton instance = null;3

4 privateSingleton() {5 System.out.println(Thread.currentThread().getName() + " 实例化单例对象");6 }7

8 public static synchronizedSingleton getInstance() {9 if (instance == null) {10 instance = newSingleton();11 }12 returninstance;13 }14

15 public voidprint() {16 System.out.println("单例模式加载");17 }18

19 }20

21 public classLazyLoadDemo {22 public static voidmain(String[] args) {23 for (int i = 0; i < 3; i++) {24 new Thread(() ->{25 Singleton.getInstance();26 }, "[单例创建者" + (i + 1) + "]").start();27 }28 }29 }

--运行结果

[单例创建者1] 实例化单例对象

Process finished with exit code0

--此时却是进行了同步处理,但是这个同步的代价却是很大的,因为效率会降低.因为整体代码中实际上只有一块区域需要同步处理,那就是instance对象的实例化处理部分,在这样的情况下同步加的未免显得有些草率,更加合理的进行同步处理:

1 classSingleton {2 //在对象实例化的时候,应该立刻与主内存中的实例对象保持同步,而不应该存在副本

3 private static volatile Singleton instance = null;4

5 privateSingleton() {6 System.out.println(Thread.currentThread().getName() + " 实例化单例对象");7 }8

9 public staticSingleton getInstance() {10 synchronized (Singleton.class) { //static方法只能使用Singleton.class

11 if (instance == null) {12 instance = newSingleton();13 }14 }15 returninstance;16 }17

18 public voidprint() {19 System.out.println("单例模式加载");20 }21

22 }23

24 public classLazyLoadDemo {25 public static voidmain(String[] args) {26 for (int i = 0; i < 3; i++) {27 new Thread(() ->{28 Singleton.getInstance();29 }, "[单例创建者" + (i + 1) + "]").start();30 }31 }32 }

java 反射应用_java反射(二)--反射应用案例相关推荐

  1. java泛型怎么用反射生成_Java 之 使用反射生成并操作对象

    一.使用反射创建对象 通过反射来生成对象有如下两种方式: 方式一: 使用 Class 对象的 newInstance() 方法来创建 Class 对象对应类的实例,这种方法要求该 Class 对象的对 ...

  2. java display.getdefault()_java基础(十一 )-----反射——Java高级开发必须懂的

    本文我们通过一个实际的例子来演示反射在编程中的应用,可能之前大家对反射的学习,仅仅是停留在概念层面,不知道反射究竟应用在哪,所以是一头雾水.相信通过这篇教程,会让你对反射有一个更深层次的认知. 概念 ...

  3. 反射 数据类型_Java基础:反射机制详解

    一.什么是反射: (1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法.本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取t对 ...

  4. java 反射 内存_Java内存到反射入门

    Java内存到反射入门(一) 初识Java内存 平常我们最常提到的的JAVA分区是这三个分区 其中方法区是一个特殊的堆,功能如图上所示. 初识反射:框架设计的灵魂 反射的功能:将类的各个组成部分封装为 ...

  5. java内省和反射机制_Java内省和反射机制三步曲之 - 内省

    经过多方面的资料搜集整理,写下了这篇文章,本文主要讲解java的反射和内省机制,希望对大家有点帮助,也希望大家提出不同的看法! 1).内省(Introspector)是 Java 语言对 Bean 类 ...

  6. java 反射教程_Java基础教程——反射机制

    Java反射机制 Java反射机制是Java语言的一个重要特性,使得Java语言具备"动态性": 在运行时获取任意一个对象所属的类的相关信息; 在运行时构造任意一个类的对象: 在运 ...

  7. java 反射泛型方法_java基础之反射和泛型以及注解

    java基础之反射和泛型以及注解 泛型擦除 泛型擦除: 泛型只在编译时期有效,编译后的字节码文件中不存在泛型信息. 声明泛型集合,集合两端类型必须一致.类型也可以用包装类型,泛型的类型必须是引用类型, ...

  8. java super关键字_Java入门(二)下

    点击蓝字关注我们 01 面向对象三大特性(2)---继承 一. 概念 继承是java三大特性之一(封装装,继承,多态).继承是从已有的类中派生出新的类.新的类继承原有类所有的属性和行为,并能拓展新的能 ...

  9. java打印系统参数_Java学习(二十):获取系统参数

    public static void main(String[] args) { Properties props = System.getProperties(); // 系统属性 System.o ...

  10. java 文件路径表达式_Java基础(二十二) Lambda表达式和File类

    函数式编程思想 强调的是做什么,而不是以什么样的方式来做,它忽略了面向对象的复杂语法,只要能够获取到结果,谁去做的,怎么做的,都不重要,重要的是结果,不重视过程. 冗余的Runnable代码 传统的写 ...

最新文章

  1. 4大主流CPU处理器技术架构,不知道就out了!
  2. AcWing 845. 八数码(3阶数字华容道):bfs求最短路,状态表示困难
  3. C~K的班级_JAVA
  4. push_back还是emplace_back?
  5. CEdit CRichEdit 使用技巧(转)
  6. python学习之老男孩python全栈第九期_day009之初始函数初窥
  7. 【南邮操作系统实验】页面置换算法 (FIFO、LRU、OPT)Java 版
  8. 20211028:DC综合时的内部时钟处理
  9. php数据库框架 edusoho,CentOS 6.x + Apache+ PHP + MySQL + EduSoho[文档]
  10. 初学Java必写的小程序。
  11. 大数据时代如何安全使用WIFI
  12. nginx发布PHP代码,nginx服务器配置返回php代码
  13. 视频教程.VB6.0+ACCESS开发数据管理软件
  14. ISE在win10中闪退解决方法以及ISE14.7安装包
  15. 什么是无刷直流电机(BLDC)以及如何使用Arduino控制它
  16. Android 悬浮窗、悬浮球开发
  17. 区块链现在的样子:当年的DOS操作系统
  18. java mye,Java - MyEclipse中国官方网站-技术交流论坛
  19. citrix vdi 服务器性能要求,Citrix测试VDI的最佳hypervisor
  20. c语言判断正整数x是否为同构数,c语言上机题库(阅读).doc

热门文章

  1. 测试女生周期的软件名字,什么软件可以提醒生理期?适合女生可用的便签软件...
  2. 【5分钟搞定】如何将py打包成exe可执行文件
  3. 2020 操作系统第二天复习(习题总结)
  4. CDH6.3.2默认管理端口是7180,HDFS相关端口
  5. Spark HistoryServer日志解析清理异常
  6. GeoMesa-空间数据存储引擎入门学习手册
  7. Vue Nuxtjs Cannot set property 'render' of undefined解决方法
  8. 【学亮IT手记】PL/SQL编程-存储过程
  9. sublime编写python路径报错怎么改_sublime开发Python的编码问题
  10. linux修改ssh登陆端口号,Linux 6 修改ssh默认远程端口号的操作步骤