“Java版本”指的是以下版本:
JDK 1.0 (1996年1月) JDK 1.1 (1997年2月) J2SE 1.2 (1998年12月) J2SE 1.3 (2000年5月) J2SE 1.4 (2002年2月) J2SE 5.0 (2004年9月) Java SE 6 (2006年12月)
注意事项: 请尽可能提供参考资料和代码示例。 请在回答中尽量具体和具体化。 被标记为@Deprecated的类不算是向后不兼容。
首先,Sun实际上认为您提到的所有发布版本(当然不包括1.0)都是“小版本”而非重大版本。
在那个时期,我不知道有任何二进制不兼容的例子。但是,有一些源代码不兼容的例子:
在Java 5中,“enum”成为了保留字;在此之前并不是。因此,在Java 1.4中可以编译的使用枚举作为标识符的源文件,在Java 5.0中将无法编译。不过,您可以使用-source 1.4编译来避免这种情况。
向接口添加方法也可能会破坏源代码的兼容性。如果您实现了一个接口,然后尝试用添加了新方法的JDK编译该实现,则源文件将不再成功编译,因为它未实现接口的所有成员。这经常发生在java.sql.Statement和其他jdbc接口中。这些“无效”实现的已编译形式仍将起作用,除非您调用了不存在的某个方法;如果这样做,将会抛出MissingMethodException异常。
这些只是我能想起来的几个例子,还可能有其他情况。
java.sql.Connection
接口从 Java 1.5 扩展到 Java 1.6,导致所有实现该接口的类的编译失败。
Swing的每个版本都会改变我们的某些东西,从1.3到1.6。
JDBC问题已经提到了,但现有的代码可以继续使用。
从1.5到1.6,Socket的行为发生了变化,这破坏了Cisco客户端。
当然,还引入了新的保留关键字。
我认为Sun公司最不可原谅的是System.getenv()。它在1.0中有效,然后被弃用并更改为在所有平台上引发错误,理由是Mac没有系统环境变量。然后,Mac得到了系统环境变量,所以在1.5中,它被取消弃用,并且可以正常工作。这没有任何合理的理由。在Mac上返回一个空集合(如果您想关注跨平台一致性的那个级别,Swing存在更大的跨平台问题),甚至在所有平台上都是如此。
我从来没有同意他们关闭该功能,但将其更改为抛出错误只是纯粹的破坏性变化,如果他们要这样做,他们应该将该方法完全删除。
但实际上,在1.0到1.1之间,他们对向后兼容性的关注较少。例如,他们放弃了“private protected”作为修饰符。
因此,总的来说,每个版本都会发生足够的变化,需要仔细评估,这就是为什么您仍然在SO上看到许多1.4问题的原因。
我能想到的主要原因是引入了新的保留字:
Java 1.3: strictfp
Java 1.4: assert
Java 5.0: enum
如果先前的任何代码使用这些值作为标识符,那么在更新版本下它们将无法编译。
我还记得在一个我参与的项目中引起问题的另一个问题是,在1.2和1.3之间更改了JInternalFrames的默认可见性。它们默认情况下是可见的,但当我们升级到1.3时,它们似乎全部消失了。
在1.3和1.4之间,Long.parseLong(String)方法对空字符串的处理方式有所不同。1.3返回0
值,而1.4会抛出NumberFormatException
异常。
不需要重新编译代码,但如果代码依赖于1.3的行为,则停止工作。
内存模型的语义从1.4版本改变到1.5版本。它被更改以允许再次使用双重检查锁定,除其他事项外。(我认为volatile语义已经修复。)它之前是有问题的。
public class Example {
public static void main(String[] args) {
String enum = "hello";
}
}
Java.sql又一次破坏了兼容性:
在1.5版本中,java.sql.Timestamp添加了compareTo(Date)方法。该方法会抛出ClassCastException异常,如果提供的Date不是java.sql.Timestamp的实例。当然,java.sql.Timestamp扩展自Date,而Date已经有一个与所有日期一起工作的compareTo(Date)方法,因此这意味着将Timestamp与(非Timestamp)Date进行比较的代码将在1.5运行时中断。
有趣的是,似乎1.6修复了这个问题。虽然java.sql.Timestamp.compareTo(Date)的文档仍然说“如果参数不是Timestamp
对象,则此方法会抛出ClassCastException
对象”,但实际实现却不是这样。我猜这是一个文档错误。