Java向后不兼容历史的观察

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

Sun Microsystems和Oracle提供了与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中包含JAXB 。 Java 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 7 , ColorChooser在具有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()结果)也可以提供帮助。

资源

  • Oracle / Sun Java版本兼容性指南(按相反顺序)
    • JDK 8兼容性指南
  • 其他相关资源
    • 升级主要Java版本(7至8)

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353052.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言中输入输出格式控制

1、C语言中&#xff0c;非零值为真&#xff0c;真用1表示&#xff1b;零值为假&#xff0c;假用0表示。 2、转义字符参考&#xff1a; \a 蜂鸣&#xff0c;响铃 \b 回退&#xff1a;向后退一格 \f 换页 \n 换行 \r 回车&#xff0c;光标到本行行首 \t 水平制表 …

java udp 接受阻塞_Java UDP发送与接收

IP地址&#xff1f;端口号&#xff1f;主机名&#xff1f;什么是Socket?什么是UDP&#xff1f;什么是TCP&#xff1f;UDP和TCP区别&#xff1f;以上问题请自行百度&#xff0c;有标准解释&#xff0c;此处不再赘述&#xff0c;直接上干货&#xff01;实例&#xff1a;发送端&a…

JavaScript 运行机制详解:Event Loop

参考地址&#xff1a;http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一、为什么JavaScript是单线程&#xff1f; JavaScript语言的一大特点就是单线程&#xff0c;也就是说&#xff0c;同一个时间只能做一件事。那么&#xff0c;为什么JavaScript不能有多个线程呢&a…

原码, 反码, 补码 详解

本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助! 一. 机器数和真值 在学习原码, 反码…

java eden space_JVM虚拟机20:内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)...

1.内存区域划分根据我们之前介绍的垃圾收集算法&#xff0c;限定商用虚拟机基本都采用分代收集算法进行垃圾回收。根据对象的生命周期的不同将内存划分为几块&#xff0c;然后根据各块的特点采用最适当的收集算法。大批对象死去、少量对象存活的&#xff0c;使用复制算法&#…

gradle 插件 自定义_Gradle自定义插件

gradle 插件 自定义本教程介绍了创建Gradle独立自定义插件的方法。 它涵盖以下主题 创建任务&#xff0c;并在“自定义”插件中使用 独立的自定义插件 简短的插件ID 使用settings.gradle自定义Gradle设置 项目信息&#xff1a; Gradle版本&#xff1a;1.1 操作系统平台&…

Pytorch常用操作

创建tensor x torch.empty(*sizes)  #创建一个未初始化的tensor&#xff08;后面用torch.nn.init中的一些函数进行初始化&#xff09; >>> torch.empty(2, 3) tensor(1.00000e-08 * [[ 6.3984, 0.0000, 0.0000], [ 0.0000, 0.0000, 0.0000]]) x torch.rand(5, 3…

数据聚合Spring Data MongoDB:嵌套结果

1引言 在上一篇文章中&#xff0c;我们构建了聚合管道的基本示例。 如果您需要有关如何创建项目和配置应用程序的更多详细信息&#xff0c;也许您想看看使用Spring Data MongoDB和Spring Boot进行数据聚合 。 在本文中&#xff0c;我们将重点研究一个用例&#xff0c;在这种情况…

如何消除img默认的间距

方案一:div{font-size:0};方案二:img{ display:block};方案三:img{vertical-align:top;}方案四&#xff1a;div{ margin-bottom:-3px }; 为什么会有间距呢&#xff1f; 根本原因在于img标签为inline元素&#xff0c;该元素默认垂直对齐方式为以父元素的baseline&#xff0c;但是…

scanf中的%[^\n]%*c格式

scanf 语法: #include <stdio.h> int scanf( const char *format, ... ); 类似函数有 int scanf(const char *format, ...); int fscanf(FILE *stream, const char *format, ...);//指定输入流 int sscanf(const char *str, const char *for…

java有理数类的封装_java实验报告有理数的类封装.doc

java实验报告有理数的类封装华中科技大学文华学院《Java程序设计》实验报告实验三&#xff1a;有理数的类封装专业班级&#xff1a; 通信工程2008级1班姓名&#xff1a;学号&#xff1a;时间&#xff1a;实验三&#xff1a;有理数的类封装1、实验目的&#xff1a;让学生学习使用…

vim基本设置

vim基本配置&#xff1a;包括tab键替换成4个空格 Edit Vim configuration file ".vimrc" in your HOME directory, add below lines: [plain] view plaincopy set et set ci set sw4 set ts4 After new setting take effect, each time you press TAB key, …

在JPA和JDBC中使用存储过程。 嗯,只要使用jOOQ

Java杂志的当前版本由Josh Juneau撰写了有关JDBC和JPA的大数据最佳实践的文章&#xff1a; http : //www.javamagazine.mozaicreader.com/MayJune2016 本文介绍了如何在JDBC中使用存储过程&#xff08;不幸的是&#xff0c;请注意如何关闭资源。即使在Java Magazine的文章中&a…

java hash sha256_Sha256加密

package com.zq.utils.encryption;import java.util.Random;import org.apache.shiro.crypto.hash.Sha256Hash;import com.zq.utils.string.StringUtils;/**** Created by MyEclipse. Author: ChenBin E-mail: chenb8000056.com Date:* 2016-5-23 Time: 下午3:10:37 Company: H…

怎样花两年时间去面试一个人

Joel Spolsky曾经感叹&#xff1a;招聘难&#xff0c;难于上青天&#xff08;此处笔者稍加演绎:)&#xff09;。他有两个辛辣但不乏洞察力的断言&#xff1a;真正的牛人也许一辈子就投大概4次简历&#xff0c;这些家伙一毕业就被好公司抢走了&#xff0c;并且他们的雇主会给他们…

非网络引用element-ui css导致图标无法正常显示的解决办法

https://blog.csdn.net/m0_37893932/article/details/79460652 ******************************************** 前言 官方推荐的css及js引用方式如下: <!-- 引入样式 --> <link rel"stylesheet" href"https://unpkg.com/element-ui/lib/theme-chalk/in…

Java EE与Java SE:Oracle是否放弃了企业软件?

Java Enterprise Edition是全球Java社区中最大的困惑来源之一。 就像《星球大战》和《星际迷航 》之间的区别一样&#xff0c;对于“原力觉醒”是他们在这部电影中看过的第一部电影的人来说。 奇怪的是&#xff0c;即使您有使用EE进行开发的经验&#xff0c;但整个情况通常仍然…

约瑟夫环

约瑟夫环是一个数学的应用问题&#xff1a;已知n个人&#xff08;以编号1&#xff0c;2&#xff0c;3...n分别表示&#xff09;围坐在一张圆桌周围。从编号为k的人开始报数&#xff0c;数到m的那个人出列&#xff1b;他的下一个人又从1开始报数&#xff0c;数到m的那个人又出列…

java链表的数据结构_Java数据结构 获取链表(LinkedList)的第一个和最后一个元素

Java数据结构 获取链表(LinkedList)的第一个和最后一个元素以下实例演示了如何使用 LinkedList 类的 linkedlistname.getFirst() 和 linkedlistname.getLast() 来获取链表的第一个和最后一个元素&#xff1a;Main.java 文件import java.util.LinkedList;public class Main {pub…

第二章:表单和模板

在第一章中&#xff0c;我们学习了使用Tornado创建一个Web应用的基础知识。包括处理函数、HTTP方法以及Tornado框架的总体结构。在这章中&#xff0c;我们将学习一些你在创建Web应用时经常会用到的更强大的功能。 和大多数Web框架一样&#xff0c;Tornado的一个重要目标就是帮助…