进阶Java编程(8)反射应用案例
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)反射应用案例的更多相关文章
- 进阶Java编程(13)反射与Annotation
1,反射取得Annotation信息 从JDK1.5之后Java提供了Annotation技术支持,这种技术为项目的编写带来了新的模型,而后经过了十年的发展,Annotation的技术得到了非常广泛的 ...
- 进阶Java编程(10)反射与简单Java类
1,传统属性自动赋值弊端 简单Java类主要由属性构成,并且提供有setter与getter类,同时简单Java类最大的特征就是通过对象保存相应的类属性的内容.但是如果使用传统的简单Java类开发,那 ...
- 进阶Java编程(9)反射与类操作
1,反射获取类结构信息 在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成结构操作,任何一个类的基本组成结构:父类(父接口).包.属性.方法(构造方法与普通方法). ...
- 进阶Java编程(7)反射机制
反射机制 1,反射机制简介 在Java语言里面之所以会有如此多的开源技术支撑,很大的一部分是来自于Java最大的特征[反射机制].如果你不能够使用反射机制去进行项目的开发与设计,那么可以说你并未接触到 ...
- Java编程之反射中的注解详解
"注解"这个词,可谓是在Java编程中出镜率比较高,而且也是一个老生常谈的话题.我们之前在聊Spring相关的东西时,注解是无处不在,之前我们简单的聊过一些"注解&quo ...
- 黑马程序员:Java编程_反射技术
=========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性 ...
- JAVA编程之——反射Reflect
说到反射,首先要说一下Java中的类和对象. 在Java中万事万物皆对象(有两个 例外,一个是普通数据类型,另一个是静态的东西,静态的东西不是对象的,是属于类的). 在Java中,类也是对象,类是ja ...
- Java编程基础-反射
一.java反射 1.反射:动态获取类的信息,以及动态调用对象的方法的功能.可以理解为动态看透类的能力. 2.主要功能:在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意 ...
- 进阶Java编程(11)ClassLoader类加载器【待完成】
1,ClassLoader类加载器简介 在Java里面提供一个系统的环境变量:ClassPath,这个属性的作用主要是在JVM进程启动的时候进行类加载路径的定义,在JVM里面可以根据类加载器而后进行指 ...
随机推荐
- 2018-2019-2 20165330《网络对抗技术》Exp10 Final 基于PowerShell的渗透实践
目录 实验内容 实验步骤 实验中遇到的问题 实验总结与体会 实验内容 PoweShell简介 PowerShell入门学习 PowerShell渗透工具介绍 相关渗透实践分析 ms15-034之Pow ...
- Failed to execute aapt
Failed to execute aapt 没错,看到这个表示你的资源出错了.不用想别的. 比如: Failed to execute aapt com.android.ide.common.pro ...
- C#剪切生成高质量缩放图片
/// <summary> /// 高质量缩放图片 /// </summary> /// <param name="OriginFilePath"&g ...
- HAproxy负载均衡-ACL篇
ACL定制法则: 开放策略:拒绝所有,只开放已知 拒绝策略:允许所有,只拒绝某些 事实上实现安全策略,无非也就是以上两种方法 redirect 参考:http://cbonte.github.io/h ...
- 几句java代码搞定十万个为什么数据
最近想做一个app,为小朋友推荐十万个为什么的故事,但是找了很久数据,发现挺难的找的,又去写爬虫,发现没有一个好的网站可以爬,最后一个偶然的机会在csdn上发现一个可用的接口,很快就把问题解决了,下面 ...
- 简单分析一下socket中的bind
[转自]守夜者 灵感来自于积累 的博客 [原文链接]http://www.cnblogs.com/nightwatcher/archive/2011/07/03/2096717.html在最开始接触b ...
- [Spark] Spark 3.0 Accelerator Aware Scheduling - GPU
Ref: Spark3.0 preview预览版尝试GPU调用(本地模式不支持GPU) 预览版本:https://archive.apache.org/dist/spark/spark-3.0.0-p ...
- idea-eclipse快捷键对比
分类 功能点 Eclipse快捷键 IDEA快捷键 搜索 搜索文本 Ctrl + F Ctrl + F Ctrl + R 查找替换 Alt + P/A 逐个/全部替换 Alt + F3 查找当前选 ...
- 9-2 yum,dnf和apt
yum, CentOS: yum, dnf YUM: Yellowdog Update Modifier,rpm的前端程序,可解决软件包相关依赖性,可在多个库之间定位软件包,up2date的替代工具 ...
- APP安全_Android渗透环境
Android渗透 移动APP大多通过WEB API服务的方式与服务端进行交互,这种模式把移动安全和web安全绑在一起.常见的web漏洞在移动APP中也存在,比如SQL注入,文件上传,中间件/serv ...