概要
  
  实现Java 众多API中的一个是一件困难的工作。你必须经常实现许多相互依赖的接口。对新特征的需求促进了最新Java API的创建,投资商们必须不断的更新他们的实现以跟上时代的需要。当复杂性和持续修改可以理解甚至被看好时, API 版本的不兼容性迫使你为更新的版本保留独立的代码库,从而N次方增加你的受挫等级。本文演示了如何克服接口版本的不兼容性,制作可为多个API版本编译的代码库的进程。
  
  Java 已经添加了无数个API,像Java 数据库连接(JDBC),到它的标准库系列上。这可以帮助更广泛的用户使用API,因为可选软件包不必捆绑到配置上。对于编写这些流行的API的工作组来说,使用的越多他们的付出就越有价值。但是,当更新的Java版本运载最新的API,而最新的API依赖的类和方法是以前的Java版本所不能实现的时候,这些工作组希望他们的API仍然是可选的(与包括在Java的标准库系列内相反)。这样你忽然必须要保留实现的两个版本——一个编译老的API,另一个编译新的API。这就是发生在Java2平台标准版(J2SE)1.4中的JDBC API身上的事情。因为修改了JDBC API, java.sql.Connection 的一个实现不能在J2SE 1.3 和 1.4版本下编译。
  
  你可能发现你自己也处于与我一样的困境中:我需要实现JDBC 接口如 java.sql.Connection,但是我的代码需要在J2SE 1.3 和1.4下编译。我不想为J2SE 1.3 和1.4保留不同的源文件,所以我寻找更好的解决方法。
  
  不幸的是,当你需要Java编译器来完成编译时著名的WORA (一次编写,各处运行)不包括WOCA (一次编写,各处编译)。幸运的是,使用Reflection API对代码做一些修改并且使用Ant 对编译做一些修改可以帮你走出困境。我能有一组.java 源文件和Ant来帮助我在J2SE 1.3 和 1.4两者之上编译代码。Ant允许我运行时修改.java文件,                               正确修改以便与编译时使用的Java版本兼容。但是在我阐述整个解决方案之前,我必须得说明整个问题。
  
   穷人的连接池
  
  两年前,我的公司需要一个JDBC连接池但是又买不起。那个时候,我们找不到好的免费的备选的东西,所以我们编写了一个内部的连接池。为了更好的追溯连接在整个我们的应用程序上是如何使用的,我们创建了com.icentris.sql.ConnectionWrapper,它实现java.sql.Connection和一些其他的可实现其他java.sql接口的包装者类。 包装者类只追踪我们应用程序内的数据库的使用并且传递方法调用到真正的JDBC资源处。
  
  当 J2SE 1.4 出来的时候,我们自然想要将一些我们的客户端程序移到它上面,这样他们就能从J2SE 1.4的许多改进中获益。但是,当然,我们仍然需要支持J2SE 1.3,因为那些客户端看不出有什么理由需要升级。我们气愤的是, ConnectionWrapper和我们其他的JDBC包装者类不修改就不能在J2SE 1.4上编译。为了保持文章的简洁,我使用ConnectionWrapper来演示我应用到所有不能同时在J2SE 1.3和 1.4下编译的类的技巧。 为了遵循最新的JDBC API,我不得不添加几个方法到ConnectionWrapper上,这造成了两个大问题:
  
  1.因为我的包装者类需要通过方法调用,我不得不调用J2SE 1.3 sql 类中没有的方法。
  
  2.因为一些新方法依赖于新的类,我不得不依赖于J2SE 1.3 中没有的类。
  
   Reflection 来拯救
  
  一些代码样品最适合解释第一个问题。因为我的ConnectionWrapper包裹了java.sql.Connection,所有我的样品依赖于构造器中的realConnection实际变量 (粗体) 组:
  
  private java.sql.Connection realConnection = null;
   
   public ConnectionWrapper(java.sql.Connection connection) {
    realConnection = connection;
   }
  
  为了看清楚我在没有不兼容问题的情况下做过什么,我们看看setHoldability(int) (到J2SE 1.4中的java.sql.Connection 的新方法):
  
  public void setHoldability(int holdability) throws SQLException {
    realConnection.setHoldability( holdability );
   }
  
  不幸的是,该代码在J2SE 1.3下不能编译因为 java.sql.Connection 没有我在J2SE 1.3才能调用的setHoldability()方法。但是要在J2SE 1.4下编译,我必须有一个setHoldability()方法可正确的实现该API. 要解决这个catch-22,我假设我的setHoldability() 方法只能在J2SE 1.4下编译,所以我可以使用Reflection API来调用该方法:
  
  public void setHoldability(int holdability) throws SQLException {
    Class[] argTypes = new Class[] { Integer.TYPE };
    Object[] args = new Object[] {new Integer(holdability)};
    callJava14Method("setHoldability", realConnection, argTypes, args);
   }
  
   public static Object callJava14Method(String methodName, Object instance,
   Class[] argTypes, Object[] args)
    throws SQLException
   {
    try {
     Method method = instance.getClass().getMethod(methodName, argTypes);
     return method.invoke(instance, args );
    } catch (NoSuchMethodException e) {
     e.printStackTrace();
     throw new SQLException("Error Invoking method (" + methodName + "): "
     + e);
    } catch (IllegalAccessException e) {
     e.printStackTrace();
     throw new SQLException("Error Invoking method (" + methodName + "): "
     + e);
    } catch (InvocationTargetException e) {
     e.printStackTrace();
     throw new SQLException("Error Invoking method (" + methodName + "): "
     + e);
    }
   }
  
  现在我有了setHoldability()方法,所以我可以在 J2SE 1.4下编译。我不直接调用我的java.sql.Connection 上以前不存在的方法,所以我能在J2SE 1.3下编译。我的 callJava14Method()方法使用 Reflection API调用该方法,然后包裹任何错误在SQLException里面,因为SQLException就是我给出的异常的全部。我将该策略用于所有新的J2SE 1.4方法,调用包裹了的方法,然后在 1.3下编译。现在我只需要解决第二个问题并且找出一条方法来依赖J2SE 1.3中不存在的类。
  
   Ant就是答案
  
  在J2SE 1.4中,java.sql.Connection依赖于新类java.sql.Savepoint。因为这个新类设置在 java.sql软件包内,你不可能将它添加到J2SE 1.3上。Java不允许添加任何第三组织的东西到java.* 或者 javax.*软件包中的核心类系列上。所以这也是对我的挑战:使用新的java.sql.Savepoint类来编写我的代码这样它就可以在J2SE 1.4下运行, 然后确保代码可在J2SE 1.3下编译,实际上,这个类在J2SE 1.3中不存在。简单,对吧?说“YES”的人都品行良好。好,至少,它简单得现在我已经找到答案了。
  
  首先,我将下列条件输入包括进来:
  
  // Comment_next_line_to_compile_with_Java_1.3
   import java.sql.Savepoint;
  
  然后为 Ant找到一条方法:当在J2SE 1.3下编译时可注释该输入。 简化之后, Ant 脚本核心部分为:
  
  <replace>
    <replacetoken>Comment_next_line_for_Java_1.3
  </replacetoken>
    <replacevalue>Comment_next_line_for_Java_1.3
  //</replacevalue>
   </replace>
  
  该 Ant 标记有几个选项——在下面的我的完整范例中你会看到更多——但是最重要的部分就是我搜索 然后用取代它。“
  
  ” 是用于"newline"的XML 实体。当在J2SE 1.4下编译时,Ant对源文件不做任何修改;并且在 J2SE 1.3下,重要语句被注释:
  
  // Comment_next_line_to_compile_with_Java_1.3
   //import java.sql.Savepoint;
  
  但是在必须依赖Savepoint 的类的体中仍有代码:
  
  public Savepoint setSavepoint(String name) throws SQLException { . . .
  
  再次,我只能期望可在J2SE 1.4下使用这些新方法,这样他们不必在J2SE 1.3下运行; 他们只需要编译。我发现:如果我的软件包中有一个Savepoint 类,我的代码不需要输入语句就可以编译。但是当输入语句没有注释的话(在J2SE 1.4编辑下),我的Savepoint 类会被忽略因为存在更特殊的输入。所以我创建了我自己的哑元类com.icentris.sql.Savepoint,它(java文章排斥它)可能是最短的有效类 :
  
  package com.icentris.sql;
  
   /** Dummy class to allow ConnectionWrapper to implement java.sql.Connection
    * and still compile under J2SE 1.3 and J2SE 1.4. When compiled
    * under J2SE 1.3, this class compiles as a placeholder instead of the
    * missing java.sql.Savepoint (not in J2SE 1.3). When compiled
    * under J2SE 1.4, this class is ignored and ConnectionWrapper uses the
    * java.sql.Savepoint that is new in J2SE 1.4.
    */
   public class Savepoint {}
  
  在J2SE 1.4下,我现在可以正确的输入java.sql.Savepoint。在J2SE 1.3下, Ant 注释输入行,这样我的代码中引用的 Savepoint正好在同一个软件包处于

克服J2SE 1.3-1.4 的不兼容性相关推荐

  1. 2020年,云操作系统市场正在爆发

    点击蓝字关注 了解更多 从最初"云是不是也应该有个操作系统"的争论,到今天云操作系统已经成了云基础架构的中枢神经,通过这十多年的培育.实践和推广,人们不再质疑"要不要上云 ...

  2. U盘文件乱码还能恢复吗

    U盘文件乱码还能恢复吗 不知道有多少朋友和我一样,本来文件是完好无损的,但是变成压缩文件再传输之后,就会出现问题,有的时候是压缩包损坏,所有的时候是压缩文件解压后出现乱码状态,这种情况真的很烦人啊. ...

  3. 克服汽车摄像头连接挑战

    克服汽车摄像头连接挑战 Overcoming automotive camera link challenges 摄像头系统和摄像头连接技术在车辆上的应用越来越广泛,以帮助驾驶员并增强驾驶体验.具有单 ...

  4. 初级开发人员的缺点_作为一名初级开发人员,我如何努力克服自己的挣扎

    初级开发人员的缺点 by Syeda Aimen Batool 通过Syeda Aimen Batool 作为一名初级开发人员,我如何努力克服自己的挣扎 (How I'm working to ove ...

  5. 学术青年如何克服拖延症——5条技巧助你前进

    雷锋网 AI 科技评论按:「我准备好了就开始」(或者说「拖延症」),以及「即便动起手来也觉得举步维艰」大概是每个现代人都逃不过的日常感受,不管是学习.在企业中工作,还是从事学术研究.我们可能都看过许多 ...

  6. 迁移学习与图神经网络“合力”模型:用DoT-GNN克服组重识别难题

    作者 | Ziling Huang.Zheng Wang.Wei Hu.Chia-Wen Lin.Shin'ichi Satoh 译者 | 刘畅 编辑 | Jane 出品 | AI科技大本营(ID:r ...

  7. 使用Mask-RCNN在实例分割应用中克服过拟合

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自AI公园 作者:Kayo Yin 编译:ronghuaiy ...

  8. 如何克服实施OKR的阻力?

    编辑说:OKR在国内不仅为字节跳动百度滴滴等大公司带来了巨大的发展收益,也催生了更多人对OKR的理解和学习,但是企业的OKR实施落地却不那么成功.OKR的落地成功到底需要克服哪些阻力呢?需要解决企业的 ...

  9. 收藏 | 使用Mask-RCNN在实例分割应用中克服过拟合

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 转载于:作者:Kayo Yin 编译:ronghuaiyang     |    AI公园 导读 只使 ...

  10. java se 与j2se_关于java:J2EE和J2SE项目之间的区别

    本问题已经有最佳答案,请猛点这里访问. 我已经从github下载了一个开源项目. 这是一个基于Maven的项目. 我如何理解该项目是J2SE项目还是J2EE项目? 这两种项目在结构上有何不同? Jav ...

最新文章

  1. C++拾趣——C++11的语法糖auto
  2. PNAS | 菌群大战:“单打独斗之殇”与“分而治之之利”
  3. 「长图」使用AI前需要评估的
  4. CVPR 2014 ObjectnessBING 原文翻译
  5. python三引号 内部变量_python在三引号中使用变量
  6. python中的类属性和实例属性
  7. .NET MVC Scripts.Render 上下文不存在问题解决方法
  8. python3安装cx oracle,[求助]python3安装cx_Oracle 报错
  9. .Net Core + NGINX跳转登录时端口丢失
  10. ASP.net C# EVal关于前端绑定
  11. *[topcoder]HexagonalBoard
  12. iPhone 11 820-01523 N104手机电路原理图+位号图
  13. Android 最常用的设计模式十 安卓源码分析——策略模式(Strategy)
  14. 如何一天做出新闻搜索引擎(1)——新闻的搜集与数据库的建立
  15. 喜报!芝诺大数据教学科研平台入选重庆市重点软件公共服务平台
  16. php版本微信公众号开发
  17. 我的优点是会使用计算机用英语怎,优点用英语,我的50个优点。
  18. php公众号菜单链接,微信公众号菜单栏添加外部链接
  19. Imagination 推出最先进的光线追踪图形处理器(GPU)
  20. 大数据分析 2021年Q3酒店品牌营销网络传播特征

热门文章

  1. 技术创新是协同OA产品的生命力
  2. bmp格式的图片怎么转jpg格式?怎么快速转图片格式?
  3. oracle打开audit,oracle开启audit(审计)
  4. Multi-Loss Weighting with Coefficient of Variations 多任务学习
  5. 服务器文档分类,服务器的分类
  6. 删除IE加载项及取消加载项的提示
  7. css中margin和padding设置成百分比时参照物是谁
  8. python class类_学习python中的class类
  9. 基于JAVA学生成绩管理系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
  10. 小象大数据全套视频教程