Java 中实例化类的动作,你是否还是一成不变 new 对应对象呢?

经手的项目多了,代码编写量自然会增加,渐渐的会对设计模式产生感觉。

怎样使书写出来的类实例化动作,高内聚,低耦合,又兼具一定的扩展能力呢?

本文试图从几段鲜活的代码入手,给大家呈现不一样的 Java 实例化类。

下面代码取自 com.google.zxing 源码实现:

  1. public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map<EncodeHintType, ?> hints) throws WriterException {
  2. Object writer;
  3. switch(format.ordinal()) {
  4. case 1:
  5. writer = new AztecWriter();
  6. break;
  7. case 2:
  8. writer = new CodaBarWriter();
  9. break;
  10. case 3:
  11. writer = new Code39Writer();
  12. break;
  13. case 4:
  14. case 10:
  15. case 13:
  16. case 14:
  17. default:
  18. throw new IllegalArgumentException("No encoder available for format " + format);
  19. case 5:
  20. writer = new Code128Writer();
  21. break;
  22. case 6:
  23. writer = new DataMatrixWriter();
  24. break;
  25. case 7:
  26. writer = new EAN8Writer();
  27. break;
  28. case 8:
  29. writer = new EAN13Writer();
  30. break;
  31. case 9:
  32. writer = new ITFWriter();
  33. break;
  34. case 11:
  35. writer = new PDF417Writer();
  36. break;
  37. case 12:
  38. writer = new QRCodeWriter();
  39. break;
  40. case 15:
  41. writer = new UPCAWriter();
  42. break;
  43. case 16:
  44. writer = new UPCEWriter();
  45. }
  46. return ((Writer)writer).encode(contents, format, width, height, hints);
  47. }
  • 其中的 BarcodeFormat 是这样的:
  1. public enum BarcodeFormat {
  2. AZTEC,
  3. CODABAR,
  4. CODE_39,
  5. CODE_93,
  6. CODE_128,
  7. DATA_MATRIX,
  8. EAN_8,
  9. EAN_13,
  10. ITF,
  11. MAXICODE,
  12. PDF_417,
  13. QR_CODE,
  14. RSS_14,
  15. RSS_EXPANDED,
  16. UPC_A,
  17. UPC_E,
  18. UPC_EAN_EXTENSION;
  19.  
  20. private BarcodeFormat() {
  21. }
  22. }
  • 源码提供的功能是将信息通过几种不同类型条形码 Wirter 输出为位矩阵,然后输出到图片上面,形成随处可见的各种类型的条形码。
    1. BitMatrix bitMatrix = new MultiFormatWriter().encode(_text, BarcodeFormat.QR_CODE, qrcodeWidth, qrcodeHeight, hints);
    2. MatrixToImageWriter.writeToFile(bitMatrix, qrcodeFormat, QrcodeFile);
  • 源码作者在这里使用了JDK 1.5  中引入的新特性 enum 枚举类,编写了BarcodeFormat类,其中定义了不同类型的条形码的属性。
  • 调用 MultiFormatWriter.encode()  根据入参 BarcodeFormat.xx 在枚举类中的序号,来实例化具体的类。
    1. switch(format.ordinal()) {
    2. case 1:
    3. writer = new AztecWriter();
    4. break;
    5. case 2:
    6. writer = new CodaBarWriter();
    7. break;
    8. case 3:
    9. writer = new Code39Writer();
    10. break;
    11. ...............
  • 这些条形码 Writer 类,同时都实现了抽象接口 Writer 的 两个encode()方法。
    1. public interface Writer {
    2. BitMatrix encode(String var1, BarcodeFormat var2, int var3, int var4) throws WriterException;
    3.  
    4. BitMatrix encode(String var1, BarcodeFormat var2, int var3, int var4, Map<EncodeHintType, ?> var5) throws WriterException;
    5. }
  • 具体的条形码 Wirter 类内部根据不同类型的条形码规则,进行不同的逻辑。
  • 使用者不需要过多的关注内部的实现,需要产生什么样子的条形码,入参选用合适的条形码类型即可,笔者上述的例子里面实现的是二维码。

在来看经典 MVC 框架 Webwork 动态实例化类的一段方法代码:

  1. private static Configuration getDefaultConfiguration () {
  2. if (defaultImpl == null) {
  3. defaultImpl = new DefaultConfiguration();
  4. try {
  5. String className = getString("webwork.configuration");
  6. if (!className.equals(defaultImpl.getClass().getName())) {
  7. try {
  8. defaultImpl = (Configuration) ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassLoader().loadClass(className));
  9. } catch (Exception e) {
  10. LOG.error("Could not instantiate configuration", e);
  11. }
  12. }
  13. return defaultImpl;
  14. } catch (IllegalArgumentException localIllegalArgumentException) {
  15. }
  16. }
  17. }
  • 源码取自 webwork-core,可能很多看客老爷没有听闻 Webwork, 但是对 Struts 应该是如雷贯耳,Struts2 核心改写自 Webwork。
  • 上述源码提供的功能为实例化用户自己定义的 配置文件读取类,该定义是在配置文件当中。
  • 源码作者在这里使用 Thread.currentThread().getContextClassLoader().loadClass(className) 线程中类加载器,动态实例化自定义配置文件读取类,可谓是效率最高的一种做法。
  • 类加载器的委托链:SystemClassloader -> ExtensionClassloader -> BootstrapClassloader
  • 委派链左边的ClassLoader就可以很自然的使用右边的ClassLoader所加载的类,类加载的机制为判断自已是否加载该类,没有在询问上级。
  • 而这三个类加载器分别对应着编译器去寻找类文件的优先级别和不同的路径:
  • BootClassLoader  由C++编写的,从 %jre%/lib 目录中加载类,或者运行时用 -Xbootclasspath 指定目录来加载。是编译器最优先寻找 class 的地方
  • ExtClassLoader  从 %jre%/lib/ext 目录加载类,或者运行时用 -Djava.ext.dirs 制定目录来加载。是编译器次优先寻找 class 的地方
  • SystemClassloader 也就是我们常说的 AppClassloader ,它对应当前路径,所以也是编译器默认找 class 的地方。
  • 平时项目中使用的 Class.forname() 会从 BootstrapClassloader 开始询问,是最消耗资源的。
  • 源码作者在这里采用线程类加载器,对应为 SystemClassloader ,效率无疑是最高的。

夜已经深了,看客老爷看完之后是否有一点点的感觉呢。

如果你不喜欢将世间万物抽象到计算机的世界,或许程序员只是你谋生的手段,你可能体会不到代码的美丽。

漫谈 Java 实例化类的更多相关文章

  1. Java的类的实例化顺序

    Java的类的实例化顺序 父类的静态数据 子类的静态数据 父类的成员变量 父类的构造方法 子类的成员变量 子类的构造方法

  2. 创建java类并实例化类对象

    创建java类并实例化类对象例一1.面向对象的编程关注于类的设计2.设计类实际上就是设计类的成员3.基本的类的成员,属性(成员变量)&方法 面向对象思想的落地法则一:1.设计类,并设计类的成员 ...

  3. JAVA 创建类,使用类

    一.创建类: Test.java //定义类 public class Test{ //属性 String name; String gender; int age; //方法,无参无返回 publi ...

  4. java 实例化是调用了子类重写方法

    java 实例化时调用了抽象方法或者class里面某个方法,如果子类有重写改方法,实际运行的是子类重写方法 package auto.test; //抽象父类 public abstract clas ...

  5. 【Demo 0004】Java基础-类封装性

    本章学习要点:       1.  Java封装特性;       2.  掌握类的定义:       3.  掌握类的调用方法; 一.封装特性        Java 纯面向对象语言,面向对象语言遵 ...

  6. java实例化对象

    摘要:分享牛,分享牛分享,java类加载机制,java实例化对象,java实例化对象机制,java基础. java是如何实例化对象的呢?以及实例化对象的先后顺序是什么?下面我们以测试的方式说明. 1. ...

  7. 第31节:Java基础-类与对象

    前言 Java基础-类与对象,方法的重载,构造方法的重载,static关键字,main()方法,this关键字,包,访问权限,类的继承,继承性,方法的重写,super变量. 方法的重载:成员方法的重载 ...

  8. java的类继承(与c++对比)

    1. interface的引入 使用interface来定义某一类通用操作,而又不强制规定其实现,对于Java的流行真是太重要了. 以JDBC举例.在Java之前,C++与数据库建立连接,常用的一个技 ...

  9. Delphi XE7的安卓程序如何调用JAVA的JAR,使用JAVA的类?

    本文使用工具和全部源码下载: http://download.csdn.net/detail/sunylat/8190765 为什么我们要在Delphi XE7的安卓程序调用JAVA的JAR,使用JA ...

随机推荐

  1. Linux 性能优化工具 perf top

    1. perf perf 是一个调查 Linux 中各种性能问题的有力工具. NAME perf - Performance analysis tools for Linux SYNOPSIS per ...

  2. org.apache.jasper.JasperException: Unable to compile class for JSP

    项目启动时报错 : The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory S ...

  3. WebService 实例

    使用Java WebService API实现 1.服务端接口: package com.h3c.itac.webservice; import javax.jws.WebService; @WebS ...

  4. Tomcat源码分析之—具体启动流程分析

    从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息 ...

  5. VBA宏 合并EXCEL

    1.合并多个Excel工作簿 Sub MergeWorkbooks() Dim FileSet Dim i As Integer Application.ScreenUpdating = False ...

  6. Linux下的压缩zip,解压缩unzip命令详解及实例

    实例:压缩服务器上当前目录的内容为xxx.zip文件 zip -r xxx.zip ./* 解压zip文件到当前目录 unzip filename.zip ====================== ...

  7. Qt5.5.0使用mysql编写小软件源码讲解---顾客信息登记表

    Qt5.5.0使用mysql编写小软件源码讲解---顾客信息登记表 一个个人觉得比较简单小巧的软件. 下面就如何编写如何发布打包来介绍一下吧! 先下载mysql的库文件链接:http://files. ...

  8. Windows Azure Storage图形界面管理工具

    上一篇我们介绍了用PowerShell将Windows Azure的存储服务当网盘来使用.如果感觉还不够简单,那么这次我们来看看还有哪些使用起来更方便的图形界面管理工具吧.当然,这些工具必要支持中国版 ...

  9. SpringMVC从入门到精通之第三章

    上一章节中首先讲解前端控制器DispatcherServlet的配置包括加载springmvc文件.拦截什么样的请求等还有两个组件:分别是适配器和映射器(另外再补充一组) 非注解的处理器映射器 处理器 ...

  10. Java方法区和运行时常量池溢出问题分析

    运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名.访问修饰符.常量池.字段描述.方法描述等. String.intern()是一个native方法,它的作用是:如果字符串常量池 ...