简体   繁体   English

Java中的最终类不应该是最终的,反之亦然?

[英]Final classes in Java which shouldn't be final or vice versa?

I was asked this question in an interview recently: 我最近在一次采访中被问到这个问题:

Can you name any class in the Java API that is final that shouldn't be or one that isn't and should be'? 你可以在Java API中命名任何不应该是最终的类,或者那个不应该且应该是'的类吗?

I couldn't think of any. 我什么都想不到。 The question implies that I should know all the API classes like the back of my hand, which I personally wouldn't expect any Java developer to know. 这个问题意味着我应该知道所有的API类,比如我的手,我个人不希望任何Java开发人员知道。

If anyone knows any such classes, please provide examples. 如果有人知道任何此类课程,请提供示例。

java.awt.Dimension isn't final or immutable and should have been. java.awt.Dimension不是final或immutable,应该是。 Anything that returns a Dimension (eg a Window object) needs to make defensive copies to prevent callers from doing nasty things. 任何返回Dimension(例如Window对象)的东西都需要制作防御性副本以防止调用者做出讨厌的事情。

The first examples that come to mind are some of the non-final Number subclasses, such as BigDecimal and BigInteger , which should probably have been final. 我想到的第一个例子是一些非最终的Number子类,比如BigDecimalBigInteger ,它们应该是最终的。

In particular, all of their methods can be overriden. 特别是,他们的所有方法都可以被覆盖。 That enables you to create a broken BigDecimal , for example: 这使您可以创建一个损坏的BigDecimal ,例如:

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

That could create significant issues if you receive BigDecimal from an untrusted code for example. 如果您从不受信任的代码接收BigDecimal,那么这可能会产生重大问题。

To paraphrase Effective Java: 用有效的Java来解释:

  • Design and document for inheritance or else prohibit it 设计和文档继承或禁止它
  • Classes should be immutable unless there's a very good reason to make them mutable 类应该是不可变的,除非有一个很好的理由使它们变得可变

In my opinion, your reply should have been that it is a matter of taste which classes should be final and which shouldn't. 在我看来,你的答复本应该是一个品味问题,哪些课程应该是最终的,哪些不应该。

There are good reasons to make Integer , Double and String all final . 有充分的理由使IntegerDoubleString都是final

There are good reasons to complain about this. 有充分理由抱怨这一点。

Then there is BitSet , BitInteger etc. which could be made final . 然后有BitSetBitInteger等可以做成final

There are a number of situations where classes are not final , but they also cannot be extended reasonably, so they probably should have been made final. 在许多情况下,课程不是final ,但它们也不能合理地扩展,因此它们可能应该是最终的。

To pick on a particular class: BitSet . 选择一个特定的类: BitSet It is not final , yet you cannot extend it to add a bit shift operation. 它不是final ,但您无法扩展它以添加shift操作。 They might as well have made it final then, or allow us to add such functionality. 他们可能final使它成为final ,或允许我们添加这样的功能。

The Date class leaps out. Date类跳出来了。 It is a mutable simple value class (essentially a wrapper around a long ), but a good heuristic is that simple value classes should be immutable. 它是一个可变的简单值类(本质上是一个long的包装器),但一个好的启发式是简单的值类应该是不可变的。 Note also its numerous deprecated methods: more evidence that the design was botched. 还要注意其众多不赞成的方法:更多证据表明设计是拙劣的。 The mutability of the Date is a source of bugs, requiring disciplined defensive copying . Date的可变性是bug的来源,需要严格的防御性复制

one that isn't and should be 一个不是也应该是的

Most final classes in java are designed so due w/ security considerations in mind, overall there are relatively few final ones. java中的大多数最终类都是基于安全性考虑而设计的,总体而言,最终的类相对较少。 For instance java.util.String is final for that very reason. 例如, java.util.String是最终的,因为这个原因。 So are many others. 许多其他人也是如此。 Some classes w/ private c-tor are declared final (Math, StrictMath) but it doesn't matter in such a case. 有些私有c-tor的类被声明为final(Math,StrictMath),但在这种情况下并不重要。

Basically unless there are security issues involved I don't care if the class is final, yet you can always use non-public c-tor w/ some factory, effectively limiting the ability to subclass. 基本上除非涉及安全问题,否则我不关心课程是否是最终的,但你总是可以使用非公共c-tor w /某些工厂,有效地限制了子类的能力。 Usually that's my preferred way as it allows package-private subclassing. 通常这是我的首选方式,因为它允许包私有子类。

In short: I can't think of a final class that should not be, however there are some that could potentially have been. 简而言之:我不能想到一个不应该的最后一堂课,但是有一些可能已经存在。 For instance java.lang.Thread being final might have not needed to protect vs malicious clone() . 例如, java.lang.Thread是final可能不需要保护vs恶意clone()

I believe java.util.Arrays and java.util.Collections should be declared final. 我相信java.util.Arraysjava.util.Collections应该声明为final。

Here is why: 原因如下:

  1. They contain only static members and a private constructor . 它们只包含静态成员和私有构造函数
  2. The private constructor prevents those classes from being extended. 私有构造函数可以防止扩展这些类。

So, those classes cannot be extended, but this fact is not visible in their public interface. 因此,这些类无法扩展,但这一事实在其公共接口中不可见。 Declaring them final would expose it and clarify intent. 宣布他们final将揭露它并澄清意图。

Additionally, java.lang.Math (another so-called utility class ) has the same structure and it is also declared final . 另外, java.lang.Math (另一个所谓的实用程序类 )具有相同的结构,并且它也被声明为final

Check the String class which is final and probably should had been your answer in the interview. 检查最后的String类,可能应该是你在面试中的答案。

Check the docs. 检查文档。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM