27

最近在一次采访中被问到这个问题:

你能命名 Java API 中任何不应该是 final 的类,或者一个不是而且应该是的类吗?

我什么都想不出来。这个问题意味着我应该知道所有的 API 类,就像我的手背一样,我个人不希望任何 Java 开发人员知道。

如果有人知道任何此类课程,请提供示例。

4

7 回答 7

22

java.awt.Dimension不是最终的或不可变的,应该是。任何返回 Dimension(例如 Window 对象)的东西都需要制作防御性副本以防止调用者做讨厌的事情。

于 2013-02-04T10:30:19.613 回答
21

想到的第一个例子是一些非最终的 Number 子类,例如BigDecimaland BigInteger,它可能应该是 final 的。

特别是,它们的所有方法都可以被覆盖。这使您能够创建一个损坏BigDecimal的 ,例如:

public class BrokenBigDecimal extends BigDecimal {
    public BigDecimal add(BigDecimal augend) {
        return BigDecimal.ZERO;
    }
}    

例如,如果您从不受信任的代码中收到 BigDecimal,这可能会产生重大问题。

套用有效的Java:

  • 设计和文件继承或禁止它
  • 类应该是不可变的,除非有充分的理由使它们可变
于 2013-02-04T10:30:10.823 回答
3

在我看来,你的回答应该是,哪些课程应该是最终的,哪些不应该是最终的,这是一个品味问题。

有充分的理由IntegerDouble而且String所有final

有充分的理由抱怨这一点。

然后是可以制作BitSet的等等。BitIntegerfinal

在很多情况下类不是final,但它们也不能合理地扩展,所以它们可能应该是 final 的。

选择一个特定的类:BitSet。不是final,但您不能扩展它来添加位shift操作。他们可能已经做到了final,或者允许我们添加这样的功能。

于 2013-02-04T10:30:34.450 回答
1

Date班级跳了出来。它是一个可变的简单值类(本质上是 a 的包装器long),但一个很好的启发是简单值类应该是不可变的。还要注意它的许多不推荐使用的方法:更多的证据表明设计是拙劣的。的可变性Date错误的来源,需要有纪律的防御性复制

于 2013-02-06T12:47:30.210 回答
0

一个不是而且应该是

Java 中的大多数 final 类都是出于安全考虑而设计的,总体而言,final 类相对较少。例如java.util.String,出于这个原因,它是最终的。许多其他人也是如此。一些带有私有 c-tor 的类被声明为 final (Math, StrictMath),但在这种情况下并不重要。

基本上除非涉及安全问题,否则我不在乎该类是否是最终的,但是您始终可以使用带有某些工厂的非公共 c-tor,从而有效地限制了子类化的能力。通常这是我的首选方式,因为它允许包私有子类化。

简而言之:我想不出一个不应该的最终课程,但是有一些可能是。例如java.lang.Thread,最终可能不需要保护与恶意clone()

于 2013-02-06T13:39:36.383 回答
0

我相信java.util.Arrays并且java.util.Collections应该被宣布为最终的。

原因如下:

  1. 它们只包含静态成员和私有构造函数
  2. 私有构造函数防止这些类被扩展。

因此,这些类无法扩展,但这一事实在其公共接口中不可见。宣布它们final将暴露它并澄清意图。

此外,java.lang.Math(另一个所谓的实用程序类)具有相同的结构,并且它也被声明final

于 2018-11-21T07:56:51.763 回答
-2

检查 String 类,它是最终的,可能应该是你在面试中的答案。

检查文档。

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html

于 2013-02-04T10:27:17.493 回答