Java设计中哪些是明确支持向后兼容性的?

6

自从这个问题重新获得了四个关闭票,我再次尝试提出一个更加具体的问题,希望社区能够更加欣赏。

Java中哪些特定的设计决策是被记录下来的,因为它们不是首选的设计决策,而是必须支持向后兼容性。

显然的例子是泛型,在运行时无法检测类型参数。(所以你不能这样做:

 public void addEmptyMember(List<?> someList) {
      if (someList instanceof List<String>) {
            ((List<String>) someList).add("");
      }
 }

在语言设计和标准API中还有哪些类似的例子?
4个回答

3
因为这个问题并没有一个单一的正确答案,我不确定它是否比你的其他问题更好。
除了通用擦除之外,我能想到的三个特性在向后兼容的名义下做出了妥协,它们分别是新的for循环语法、可变参数和自动装箱。
新的for循环语法可能应该写成for(item in List),但这会需要将in变成保留字。这会导致许多向后兼容性问题,其中最小的问题是System.in必须被重命名。
可变参数和自动装箱都增加了歧义的可能性。例如,如果将一个对象数组传递给一个接受Object...的方法,这是否意味着应该将数组作为可变参数数组的元素传递还是作为可变参数数组本身?如果存在重载,则会变得更加复杂。自动装箱也有类似的重载歧义问题。解决这些问题的方法是制定一个规则,在解决方法调用时,首先使用1.5版本之前的规则进行解决(即没有自动装箱,并且Object...被视为Object[])。只有当方法调用不能使用1.5版本之前的规则进行解决时,才考虑新的1.5版本规则。

第三个选项真的只是为了向后兼容而被选择吗?在我看来,即使没有考虑向后兼容性,它似乎也是有意义的。 - Jens Schauder
4
在任何实现中,如果语言一开始就有可变参数(varargs),你需要为“展开这个数组并将其元素作为参数传递给 varargs”设计独立的语法。(例如,在 Python 中使用 *args 调用符号,或者在 Lisp 中使用 apply 函数。)然而,他们不想在 Java 中这样做,因为他们希望能够“升级”现有的 API 函数以使用 varargs,同时仍然让所有旧的调用者(期望一个数组)正常工作。 - Laurence Gonsalves

3

标准库中有很多例子

  • java.awt.Color具有相同的常量,其中包含大小写名称
  • 由于java.util.Calendar的引入,所有已弃用的方法在java.util.Date中 - 真是一团糟!!
  • 仍在使用java.util.Enumeration的类,可以使用java.util.Iterator替换它
  • Swing中接受向量作为参数的类,但可以添加支持java.util.Collection

2

另一个问题是,一些类和方法已经被多个版本淘汰,但仍然存在。其中最明显的就是各种线程方法,它们已经被弃用了。


2
当然是真的。我记得他们将System.getenv()改为抛出异常而不是返回结果 - 但是他们为了向后兼容性而保留了该方法! - Yishai
除了“destroy”方法之外,所有其他已弃用的线程方法都有一定的用途,包括暂停/恢复和停止一直是有用的,尽管强烈不建议使用。 - bestsss


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接