改造无效方法以返回其参数以促进流畅性:重大更改?
“API设计就像性:犯一个错误,并在你的余生中支持它”(Josh Bloch在twitter上)
Java 库中有许多设计错误。 (讨论),我们无法在不造成破损的情况下解决这个问题。我们可以尝试弃用(讨论),但它可能会永远存在。Stack extends Vector
Integer.getInteger
尽管如此,某些类型的改造可以在不造成破损的情况下进行。
有效的Java第2版,第18项:更喜欢接口而不是抽象类:可以很容易地改造现有类以实现新接口”。
示例:、等。String implements CharSequence
Vector implements List
有效的 Java 第 2 版,第 42 项:明智地使用 varargs:您可以改造一个以数组作为其最终参数的现有方法,以采用 varags,而不会影响现有客户端。
一个(不)著名的例子是,它引起了混乱(讨论),但没有破损。Arrays.asList
这个问题是关于另一种改造的:
你能改造一个方法来返回一些东西而不破坏现有的代码吗?void
我最初的预感指向是的,因为:
- 返回类型不会影响在编译时选择哪种方法
- 请参见: JLS 15.12.2.11 - 未考虑返回类型
- 因此,更改返回类型不会更改编译器选择的方法
- 从改装到返回某些东西是合法的(但不是相反!
void
- 即使您使用反射,像
Class.getMethod
这样的东西也不会区分返回类型。
但是,我希望听到其他在Java / API设计方面更有经验的人的更彻底的分析。
附录:动机
正如标题中所建议的那样,一个动机是促进流畅的界面风格编程。
考虑一下这个简单的代码段,它打印了一个随机排列的名称列表:
List<String> names = Arrays.asList("Eenie", "Meenie", "Miny", "Moe");
Collections.shuffle(names);
System.out.println(names);
// prints e.g. [Miny, Moe, Meenie, Eenie]
如果 Collections.shuffle(List)
被声明为返回输入列表,我们可以这样写:
System.out.println(
Collections.shuffle(Arrays.asList("Eenie", "Meenie", "Miny", "Moe"))
);
还有其他方法,如果它们返回输入列表而不是,例如反向(列表),sort
(List)
等,使用起来会更愉快。事实上,拥有和返回是特别不幸的,因为它剥夺了我们编写这样的富有表现力的代码:Collections
void
Collections.sort
Arrays.sort
void
// DOES NOT COMPILE!!!
// unless Arrays.sort is retrofitted to return the input array
static boolean isAnagram(String s1, String s2) {
return Arrays.equals(
Arrays.sort(s1.toCharArray()),
Arrays.sort(s2.toCharArray())
);
}
当然,这种防止流利度的返回类型不仅限于这些实用方法。java.util.BitSet
方法也可以编写为返回 (ala 和 )以促进流畅性。void
this
StringBuffer
StringBuilder
// we can write this:
StringBuilder sb = new StringBuilder();
sb.append("this");
sb.append("that");
sb.insert(4, " & ");
System.out.println(sb); // this & that
// but we also have the option to write this:
System.out.println(
new StringBuilder()
.append("this")
.append("that")
.insert(4, " & ")
); // this & that
// we can write this:
BitSet bs1 = new BitSet();
bs1.set(1);
bs1.set(3);
BitSet bs2 = new BitSet();
bs2.flip(5, 8);
bs1.or(bs2);
System.out.println(bs1); // {1, 3, 5, 6, 7}
// but we can't write like this!
// System.out.println(
// new BitSet().set(1).set(3).or(
// new BitSet().flip(5, 8)
// )
// );
不幸的是,与 / 不同,所有的 mutator 都返回 。StringBuilder
StringBuffer
BitSet
void