1,反射实例化对象

  经过一系列分析之后可以发现虽然获得了Class类的实例化对象但是依然觉得这个对象获取的意义不是很大,所以为了进一步的帮助大家理解反射的核心意义所在,下面将通过几个案例进行说明(都是实际开发之中一定会使用到)。

·反射实例化对象

  获取Class对象之后最大的意义实际上并不是在于只是一个对象实例化操作的形式,更是重要的是Class类里面提供有一个对象的反射实例化方法(代替关键字new):

  ·在JDK1.9以前的实例化:public T newInstance() throws InstantiationException,IllegalAccessException

  ·JDK1.9之后:class.getDeclaredConstructor().newInstance()

·范例:通过newInstance()方法实例化Person类对象

 1 package cn.mufasa.demo;
2 public class Person1 {
3 //任何情况下如果要进行实例化一定要调用类中的构造方法
4 //为类中的属性初始化
5 public Person1(){
6 System.out.println("***无参构造方法***");
7 }
8 @Override
9 public String toString(){
10 return "一个Person类";
11 }
12 }
 1 package cn.mufasa.demo;
2 public class JavaAPIDemo6 {
3 public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
4 Class<?> cls=Class.forName("cn.mufasa.demo.Person1");
5 Object obj=cls.newInstance();//实例化对象,JDK1.9之后非常Deprecated【弃用】
6 System.out.println(obj);//输出对象调用toString
7 }
8 }
9 /*输出
10 【cls.newInstance()】***无参构造方法***
11 【System.out.println(obj)】一个Person类
12 */

  现在通过反射实现的对象实例化处理,依然要调用类中的无参构造方法,其本质等价于【new 对象=new 类()】,相当于隐藏了关键字new,而直接使用字符串进行了替代。

  ·范例:从JDK1.9之后newInstance()被替代

 1 package cn.mufasa.demo;
2 public class JavaAPIDemo7 {
3 public static void main(String[] args) throws Exception {
4 Class<?> cls=Class.forName("cn.mufasa.demo.Person1");
5 Object obj=cls.getDeclaredConstructor().newInstance();//JDK1.9之后,构造方法的实例化
6 System.out.println(obj);
7 }
8 }
9 /*输出
10 ***无参构造方法***
11 一个Person类
12 */

  原因:Class类中的newInstance只能够调用无参构造,很多开发者认为其描述的不准确,于是将其变换了形式(构造方法会讲解)。

2,反射与工厂设计模式

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

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

  ·范例:传统工厂设计模式

 1 package cn.mufasa.demo;
2 public class JavaAPIDemo8 {
3 public static void main(String[] args) throws Exception {
4 IMessage msg=new NetMessage();//如果直接实例化一定会有耦合问题
5 msg.send();
6 }
7 }
8 /*输出
9 【网络消息发送】www.cnblogs.com
10 */

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

  ·范例:利用工厂模式解决此类问题

 1 package cn.mufasa.demo;
2 public class Factory {
3 private Factory(){}//没有产生实例化对象的意义,所以构造方法私有化
4 public static IMessage getInstance(String className){
5 if("netmessage".equalsIgnoreCase(className)){
6 return new NetMessage();
7 }
8 return null;
9 }
10 }
 1 package cn.mufasa.demo;
2 public class JavaAPIDemo9 {
3 public static void main(String[] args) throws Exception {
4 IMessage msg=Factory.getInstance("NetMessage");//标准的工厂设计模式
5 msg.send();
6 }
7 }
8 /*输出
9 【网络消息发送】www.cnblogs.com
10 */

  此种工厂设计模式属于静态设计模式,也就是说如果现在要追加一个子类,则意味着工厂类一定要做出修改,因为如果不追加这种判断是无法获取指定接口对象的。

  ·范例:为IMessage追加一个子类

 1 package cn.mufasa.demo;
2 public class Factory1 {
3 private Factory1(){}//没有产生实例化对象的意义,所以构造方法私有化
4 public static IMessage getInstance(String className){
5 if("netmessage".equalsIgnoreCase(className)){
6 return new NetMessage();
7 }else if("cloudmessage".equalsIgnoreCase(className)){
8 return new CloudMessage();
9 }
10 return null;
11 }
12 }
 1 package cn.mufasa.demo;
2 public class JavaAPIDemo10 {
3 public static void main(String[] args) throws Exception {
4 IMessage msg=Factory1.getInstance("cloudmessage");//标准的工厂设计模式
5 msg.send();
6 }
7 }
8 /*输出
9 【云消息】www.cnblogs.com
10 */

  工厂设计模式最有效解决的是子类与客户端的耦合问题,但是解决的核心思想是在于提供有一个工厂类作为过渡端,但是随着项目的进行,你的IMessage类可能会有更多的子类,而且随着时间的推移子类产生的可能越来越多,那么此时就意味着,你的工厂类永远都要进行修改,并且永无停止之日!!!这种静态工厂在实际开发中不被采用,如果想要编码一次工厂类满足所有子类,那么其中的判断【if】语句是不允许增加的。

  那么这个时候最好的解决方案就是不使用关键字new来完成,因为关键字new在使用的时候需要有一个明确的类存在。而newInstance()方法只需要有一个明确表示类名称的字符串即可应用。

 1 package cn.mufasa.demo;
2 public class Factory2 {
3 private Factory2(){}
4 public static IMessage getInstance(String className) throws Exception {
5 IMessage instance=null;
6 try{//动态工厂类
7 instance=(IMessage) Class.forName(className).getDeclaredConstructor().newInstance();
8 }catch (Exception e){
9 e.printStackTrace();
10 }
11 return instance;
12 }
13 }
 1 package cn.mufasa.demo;
2 public class JavaAPIDemo11 {
3 public static void main(String[] args) throws Exception {
4 IMessage msg=Factory2.getInstance("cn.mufasa.demo.CloudMessage");
5 msg.send();
6 }
7 }
8 /*输出
9 【云消息】www.cnblogs.com
10 */

  这个时候发现利用工厂类设计模式,最大的优势在于接口子类的扩充将不再影响到工厂类的定义。

  但是现在依然需要进一步思考,因为在实际的项目开发过程中有可能会有大量的接口,并且这些接口都可能需要通过工厂类实例化,所有此时的工厂设计模式不应该只为一个IMessage接口服务,而应该为所有的接口服务。

  ·范例:终极的工厂设计模式【没有耦合-无视接口、子类等等】

1 package cn.mufasa.demo;
2 public interface IService {
3 public void service();
4 }
1 package cn.mufasa.demo;
2 class HouseService implements IService{
3 @Override
4 public void service() {
5 System.out.println("【服务】住宿服务");
6 }
7 }
 1 package cn.mufasa.demo;
2 public class JavaAPIDemo12 {
3 public static void main(String[] args) throws Exception {
4 IMessage msg=Factory3.getInstance("cn.mufasa.demo.CloudMessage",IMessage.class);
5 msg.send();
6 IService service=Factory3.getInstance("cn.mufasa.demo.HouseService",IService.class);
7 service.service();
8 }
9 }
10 /*输出
11 【云消息】www.cnblogs.com
12 【服务】住宿服务
13 */
 package com.cnblogs.mufasa.Demo2;

 public class Factory3 {
private Factory3(){} /**
* 获取接口实例化对象
* @param className 接口的子类
* @param tClass 描述的是一个接口的类型
* @param <T> 接口的类型【泛型】
* @return 如果子类存在则返回指定接口的实例化对象
* @throws Exception
*/
public static <T> T getInstance(String className,Class<T> tClass) throws Exception {
T instance=null;
try{//动态工厂类
instance=(T) Class.forName(className).getDeclaredConstructor().newInstance();
}catch (Exception e){
e.printStackTrace();
}
return instance;
}
}

  此时的工厂设计模式将不再受限于指定的接口,可以为所有的接口提供实例化操作,大大提高了可重用性。

进阶Java编程(8)反射应用案例的更多相关文章

  1. 进阶Java编程(13)反射与Annotation

    1,反射取得Annotation信息 从JDK1.5之后Java提供了Annotation技术支持,这种技术为项目的编写带来了新的模型,而后经过了十年的发展,Annotation的技术得到了非常广泛的 ...

  2. 进阶Java编程(10)反射与简单Java类

    1,传统属性自动赋值弊端 简单Java类主要由属性构成,并且提供有setter与getter类,同时简单Java类最大的特征就是通过对象保存相应的类属性的内容.但是如果使用传统的简单Java类开发,那 ...

  3. 进阶Java编程(9)反射与类操作

    1,反射获取类结构信息 在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成结构操作,任何一个类的基本组成结构:父类(父接口).包.属性.方法(构造方法与普通方法). ...

  4. 进阶Java编程(7)反射机制

    反射机制 1,反射机制简介 在Java语言里面之所以会有如此多的开源技术支撑,很大的一部分是来自于Java最大的特征[反射机制].如果你不能够使用反射机制去进行项目的开发与设计,那么可以说你并未接触到 ...

  5. Java编程之反射中的注解详解

    "注解"这个词,可谓是在Java编程中出镜率比较高,而且也是一个老生常谈的话题.我们之前在聊Spring相关的东西时,注解是无处不在,之前我们简单的聊过一些"注解&quo ...

  6. 黑马程序员:Java编程_反射技术

    =========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性 ...

  7. JAVA编程之——反射Reflect

    说到反射,首先要说一下Java中的类和对象. 在Java中万事万物皆对象(有两个 例外,一个是普通数据类型,另一个是静态的东西,静态的东西不是对象的,是属于类的). 在Java中,类也是对象,类是ja ...

  8. Java编程基础-反射

    一.java反射 1.反射:动态获取类的信息,以及动态调用对象的方法的功能.可以理解为动态看透类的能力. 2.主要功能:在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意 ...

  9. 进阶Java编程(11)ClassLoader类加载器【待完成】

    1,ClassLoader类加载器简介 在Java里面提供一个系统的环境变量:ClassPath,这个属性的作用主要是在JVM进程启动的时候进行类加载路径的定义,在JVM里面可以根据类加载器而后进行指 ...

随机推荐

  1. OUC_Summer Training_ DIV2_#2之解题策略 715

    这是第一天的CF,是的,我拖到了现在.恩忽视掉这个细节,其实这一篇只有一道题,因为这次一共做了3道题,只对了一道就是这一道,还有一道理解了的就是第一篇博客丑数那道,还有一道因为英语实在太拙计理解错了题 ...

  2. (转载)完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三

    转自:http://blog.csdn.net/piggyxp/article/details/6922277 前 言 本系列里完成端口的代码在两年前就已经写好了,但是由于许久没有写东西了,不知该如何 ...

  3. 之前有面试到两个日期的大小比较方式,现在整理一下几种方法。   例子:   String beginTime=new String("2017-06-09 10:22:22");     String endTime=new String("2017-05-08 11:22:22");  1  直接用Date自带方法before()和after()比较 SimpleDateFormat d

    各种数据类型(日期/时间.integer.floating point和numeric)转换成格式化的字符串以及反过来从格式化的字符串转换成指定的数据类型.下面列出了这些函数,它们都遵循一个公共的调用 ...

  4. 汽车辐射监测系统-Qt开发[转]发

    功能介绍: 利用在路边的两个探测器,探测汽车的辐射剂量,通过电子板进行数据采集,并串口传输到计算机,实时显示.可以保存采集数据,进行独立显示. 开发环境: VS2008,Qt4.7, QWT 6.0. ...

  5. Android网络编程之——文件断点下载

    一:关于断点下载所涉及到的知识点 1.对SQLite的增删改查(主要用来保存当前任务的一些信息) 2.HttpURLConnection的请求配置 HttpURLConnection connecti ...

  6. android Activity,Fragment,Application内存状态监听及等级

    @Override public void onTrimMemory(int level) { super.onTrimMemory(level); switch (level){ case TRIM ...

  7. 实现超简单的http服务器

    想在Linux下实现一个简单的web Server并不难.一个最简单的HTTP Server不过是一个高级的文件服务器,不断地接收客户端(浏览器)发送的HTTP请求,解析请求,处理请求,然后像客户端回 ...

  8. React Native安卓代码混淆和打包

    一上午就整了个React Native的打包,中间还遇到各种问题,这里还是记录下吧: 文档链接: http://reactnative.cn/docs/0.45/signed-apk-android. ...

  9. QQ群关系数据库处理

    1.附加数据库 EXEC sp_attach_single_file_db @dbname= 'GroupData1_Data' , @physname= '/media/disk4/share/Da ...

  10. java数据结构之LinkedList

    一.LinkedList源码注释 //LinkedList源码 jdk版本1.8.0_121 public class LinkedList<E> extends AbstractSequ ...