最近在一次采访中被问到这个问题:
你能命名 Java API 中任何不应该是 final 的类,或者一个不是而且应该是的类吗?
我什么都想不出来。这个问题意味着我应该知道所有的 API 类,就像我的手背一样,我个人不希望任何 Java 开发人员知道。
如果有人知道任何此类课程,请提供示例。
java.awt.Dimension
不是最终的或不可变的,应该是。任何返回 Dimension(例如 Window 对象)的东西都需要制作防御性副本以防止调用者做讨厌的事情。
想到的第一个例子是一些非最终的 Number 子类,例如BigDecimal
and BigInteger
,它可能应该是 final 的。
特别是,它们的所有方法都可以被覆盖。这使您能够创建一个损坏BigDecimal
的 ,例如:
public class BrokenBigDecimal extends BigDecimal {
public BigDecimal add(BigDecimal augend) {
return BigDecimal.ZERO;
}
}
例如,如果您从不受信任的代码中收到 BigDecimal,这可能会产生重大问题。
套用有效的Java:
在我看来,你的回答应该是,哪些课程应该是最终的,哪些不应该是最终的,这是一个品味问题。
有充分的理由Integer
,Double
而且String
所有final
。
有充分的理由抱怨这一点。
然后是可以制作BitSet
的等等。BitInteger
final
在很多情况下类不是final
,但它们也不能合理地扩展,所以它们可能应该是 final 的。
选择一个特定的类:BitSet
。不是final
,但您不能扩展它来添加位shift
操作。他们可能已经做到了final
,或者允许我们添加这样的功能。
Date
班级跳了出来。它是一个可变的简单值类(本质上是 a 的包装器long
),但一个很好的启发是简单值类应该是不可变的。还要注意它的许多不推荐使用的方法:更多的证据表明设计是拙劣的。的可变性Date
是错误的来源,需要有纪律的防御性复制。
一个不是而且应该是
Java 中的大多数 final 类都是出于安全考虑而设计的,总体而言,final 类相对较少。例如java.util.String
,出于这个原因,它是最终的。许多其他人也是如此。一些带有私有 c-tor 的类被声明为 final (Math, StrictMath),但在这种情况下并不重要。
基本上除非涉及安全问题,否则我不在乎该类是否是最终的,但是您始终可以使用带有某些工厂的非公共 c-tor,从而有效地限制了子类化的能力。通常这是我的首选方式,因为它允许包私有子类化。
简而言之:我想不出一个不应该的最终课程,但是有一些可能是。例如java.lang.Thread
,最终可能不需要保护与恶意clone()
。
我相信java.util.Arrays
并且java.util.Collections
应该被宣布为最终的。
原因如下:
因此,这些类无法扩展,但这一事实在其公共接口中不可见。宣布它们final
将暴露它并澄清意图。
此外,java.lang.Math
(另一个所谓的实用程序类)具有相同的结构,并且它也被声明final
。
检查 String 类,它是最终的,可能应该是你在面试中的答案。
检查文档。
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html