java向后兼容吗_Java向后不兼容历史的观察

java向后兼容吗

在大多数情况下,Java是一个非常向后兼容的编程语言。 这样做的好处是,与大规模破坏兼容性相比,大型系统通常可以相对轻松的方式升级为使用Java的较新版本。 这样做的主要缺点是Java坚持了一些设计决策,这些决策自那时以来就被认为比理想情况要差,但必须留在原处以保持一般的向后兼容性。 即使Java与向后兼容性有相当强的联系,但Java的每个主要版本中仍存在差异,这些差异可能会在升级时破坏基于Java的应用程序。 这些可能发生的中断(最常见于“拐角事件”中)是本文的主题。

Sun MicrosystemsOracle提供了与Java升级相关的兼容性问题的相当详细的概述。 我的观点不是要涵盖所有版​​本中的所有这些问题,而是要强调随Java的每个主要发行版引入的一些关键的不兼容性问题,这些问题要么对我个人造成影响,要么对其他人产生更大影响。 这篇文章底部的链接提供给Sun / Oracle Java版本的兼容性文档,以帮助那些寻求更大范围的读者。

升级

事后看来,Java的这一早期发行版修复了实现与规范的一些不兼容性也就不足为奇了。 例如, JDK 1.2兼容性参考指出,在1.1版本中实现的String哈希函数与Java语言规范第一版中指定的函数不匹配,并且实际上是无法实现的。” 它补充说,“已实现的函数在某些类别的字符串上执行得非常差”,并解释说,实现了“ 1.2版中新的String哈希函数”是为了“使实现符合规范并解决性能问题。” 尽管可以预料到对String.hashCode()的更改不会影响大多数应用程序,但是,人们公认“具有依赖于实际String哈希值的持久性数据的应用程序……理论上可能会受到影响。” 提醒您,依赖对象的hashCode()方法返回特定代码通常不是一个好主意。

升级

JDK 1.3兼容性参考提到了一些更改,这些更改带来了更多与JDK规范的实现一致性。 这样的一个例子是引入了“类型和子包之间的名称冲突”的更改:


根据…Java语言规范,…包中包含类或接口类型以及具有相同名称的子包是非法的。 在1.3版之前,几乎从未执行过此规则。 现在,新的编译器将一致地执行此规则。 如果在类路径或源路径上可以访问相应的目录,源文件或类文件,则不管其内容如何,​​都可以认为包,类或接口存在。

JDK 1.3还对“方法java.lang.Double.hashcode的实现”进行了更改。

升级

由于JDK 1.4的更改,我在一个项目上升级到JDK 1.4的升级工作最终花费的时间比估计的时间长,因此“编译器现在拒绝从未命名空间中导入类型的导入语句。” 换句话说,JDK 1.4取消了导入定义而无需显式包的类的功能。 我们没有意识到这对我们来说将是一个问题,因为它所影响的代码是由第三方工具生成的代码。 我们没有控制代码的生成以强制生成的类位于命名包中,因此它们自动成为“未命名名称空间”的一部分。 这意味着,使用JDK 1.4,我们将无法再将这些生成的类与我们自己的源代码一起编译 。 发现并解决此更改花费的时间比我们预期的要长,或者我们认为这将是相对简单的JDK版本升级。 当一个人控制代码时,同一JDK 1.4兼容性参考也指出了最合适的解决方案:“将所有类从未命名的名称空间移到命名的名称空间。”

升级

我在上一篇文章“ 关于避免对toString()Result进行解析或基于逻辑的美德”中写过Java SE 5对BigDecimal.toString()的更改。 Java SE 5兼容性参考只是指出:“ J2SE 5.0 BigDecimaltoString()方法的行为与早期版本不同。”

升级到Java SE 6时,最让我困扰的问题是JDK 6中包含JAXBJava SE 6兼容性参考中未列出此问题,因为此问题的性质在技术上不符合此处记录的兼容性问题的定义。 但是,在迁移到Java SE 6之前使用单独下载的JAXB JAR的任何人都可能遇到了我遇到的类加载器问题我们大多数人过去用来解决此问题的解决方案是将首选的JAXB JAR放置在指定的目录中,该目录是Java认可的标准替代机制的一部分从Java 8开始不推荐使用, 在Java 9中已删除 )。

升级

升级到Java 7时, com.sun.image.codec.jpeg软件包的任何使用都被中断。Java 7兼容性参考指出,“ com.sun.image.codec.jpeg软件包已在JDK 1.2中添加(1998年12月)。作为控制JPEG格式图像文件的加载和保存的非标准方式 。 该软件包从不属于平台规范的一部分,已从Java SE 7发行版中删除。 Java Image I / O API已作为标准API添加到JDK 1.4版本中,从而不再需要com.sun.image.codec.jpeg package 。”

Java 7中重新引入的另一个不兼容性实际上是使实现更好地符合规范的另一个示例。 在这种情况下,在Java SE 6中,具有基本相同的已删除签名但具有不同返回类型的方法被视为两种不同的方法。 这不符合规范,Java 7对此进行了修复。 关于此问题的更多详细信息,请参见我的博客文章NetBeans 7.1的Internal Compiler和JDK 6尊重方法重载的返回类型以及Java 7兼容性参考中 “摘要”标题下的内容:类无法定义相同擦除的两个方法签名,但有两种不同的返回类型”和“编译器不允许使用具有相同擦除签名的非重写方法”。

Java 7升级也为Substance用户带来了一些困难。 非实质性6.2版本的帖子指出:“ Java 7修复– Java的颜色选择器中的一个错误修复破坏了6.1的实质。 这个问题在Substance 6.2中已修复,因此现在应该可以在Java 7上运行!” 破坏了Substance的JDK 7更改已在许多地方记录,包括具有Substance外观的JColorChooser,Java 7ColorChooser在具有JDK7的JSlider中导致NullPointerException以及颜色选择器setColor在Java 7中不起作用

升级

就像Java 7的更改影响了实质性的一样,Java 8带来的更改也直接影响了几个流行且广泛使用的Java库。 尽管此更改可能直接影响了相对较少的Java应用程序,但它间接地有可能影响许多Java应用程序。 幸运的是,这些Java库的维护人员倾向于快速解决此问题。 这是另一个实施规范的例子,该规范被严格化(更正)并破坏基于无法正确实施规范的实现而起作用的事物。 在这种情况下,更改/更正在字节码验证程序中。 《 JDK 8兼容性指南》指出:“当指令引用实例初始化方法(“ <init> ”)时,invokespecial指令的验证已加强。 Niv Steingarten的博客文章Oracle最新的Java 8更新破坏了您的工具—它是如何发生的?

升级

Java 9似乎会引入一些重大的向后兼容性问题 ,尤其是考虑到模块化的引入。 虽然这些破损是什么尚待观察,但最初的提议已经引起轩然大波 ,该提议取消了对sun.misc.Unsafe的访问。 这是另一个示例,其中官方不支持的API可能不会被大多数应用程序直接使用,而是可能被众多应用程序间接使用 ,因为它们依赖的库和产品都在使用它。 有趣的是,这引起了Mark Reinhold的提议 ,即将内部API封装在JDK 9中。考虑到与主要Java版本之间删除和更改的内部API相关的众多兼容性问题,这似乎是个好主意。

  • 避免利用违反规范的不正确实现,因为在更改实现以强制执行规范时,实现中的漏洞利用可能根本不起作用。
  • 提防并谨慎使用任何宣传为试验性或在将来的Java版本中删除的API,类和工具。 这包括sun。*软件包以及不建议使用的工具和API。
    • 我喜欢提议的“将内部API封装在JDK 9中”的JDK 9方法来解决主要版本升级中的这些常见问题。
  • 不要依赖 toString()实现返回的String来实现程序逻辑。

结论

多年来,为了保持Java在很大程度上向后兼容,已经进行了大量的努力。 但是,在某些情况下不能保持这种向后兼容性。 我在这篇文章中看了一些例子,并从这些例子中提取了一些观察和教训。 当开发人员避免使用已弃用的功能,避免使用实验性功能以及避免使用非标准功能时,向Java新版本的迁移往往会更容易。 此外,某些编码实践(例如避免将逻辑基于toString()结果)也可以提供帮助。

资源

翻译自: https://www.javacodegeeks.com/2016/06/observations-history-java-backwards-incompatibility.html

java向后兼容吗

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值