27

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'?

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.

If anyone knows any such classes, please provide examples.

sotn
  • 1,833
  • 5
  • 35
  • 65
  • 2
    Probably the test is about your experience with Java API, it doesn't mean that you should know it by heart. – Bogdan Feb 04 '13 at 10:27
  • 3
    At some points, mainly when debugging horrible code, I would suggest that `Object` should have been made final. – Kevin Bowersox Feb 04 '13 at 10:28
  • 3
    You didn't make it clear what question you want to ask. Are you looking for an example, or opinion on the interview question, or else? – Alvin Wong Feb 04 '13 at 10:28
  • what did you answer to the panelist? – DDK Feb 04 '13 at 10:29
  • @DDK, my answer was pretty similar to Anony-Moussse, except I couldn't come up with the BitSet class. – sotn Feb 04 '13 at 10:45
  • @Quoi, you have no idea how wrong you are. AtomicInteger, AtomicLong SHOULD NOT be final. Collection framework being final would be beyond a terrible idea and stuff like JDO would not be implemented. – bestsss Feb 06 '13 at 12:57

7 Answers7

22

java.awt.Dimension isn't final or immutable and should have been. Anything that returns a Dimension (e.g a Window object) needs to make defensive copies to prevent callers from doing nasty things.

Michael Barker
  • 14,153
  • 4
  • 48
  • 55
  • It's not immutable due to in the days of old, creating new objects (and subsequent GC) was not exactly cheap, likewise Point/Rectangle. Those classes should been value type alike but at the moment java lack such provision. – bestsss Feb 06 '13 at 13:06
  • Unfortunately it was an invalid optimisation. Leaving it mutable meant the necessity to create defensive copies that leave to increased allocation/garbage not less. – Michael Barker Feb 06 '13 at 18:59
  • How so? you pass the dimension as parameter, that was the idea. Also the copies are necessary only to client-space code, inside the awt the object is accessed by its fields (no copies). I do not defend leaving public fields of dimension, though.. just explaining - making it final would not have helped on its own. – bestsss Feb 06 '13 at 19:01
  • Have a look at the `size()` method on `java.awt.Component` it copies the Dimension object every time it is called. You're right making it final is a necessary but not sufficient condition for immutability. – Michael Barker Feb 07 '13 at 03:22
  • `size()`, itself, is deprecated, so I suppose you meant `getSize()`. Look at the right method: `Dimension size(Dimension rv)` - this is what I mean. That was the design philosophy - pass the object to be filled in, if you pass null you get brand new object. – bestsss Feb 07 '13 at 07:56
21

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.

In particular, all of their methods can be overriden. That enables you to create a broken BigDecimal, for example:

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.

To paraphrase Effective 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
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 1
    You can design broken list/collection/etc, BigDecimal,BigInteger are ok not being final imo. You can track them if you want to. Being final won't help anything in their case. – bestsss Feb 06 '13 at 13:00
3

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.

There are good reasons to complain about this.

Then there is BitSet, BitInteger etc. which could be made 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.

To pick on a particular class: BitSet. It is not final, yet you cannot extend it to add a bit shift operation. They might as well have made it final then, or allow us to add such functionality.

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194
  • I don't think it is only a matter of taste - Many security features of the Java programming language depend upon String objects being immutable for example. And if you want mutability, you have the mutable companion class, StringBuilder. – assylias Feb 04 '13 at 10:54
1

The Date class leaps out. 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. 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.

Community
  • 1
  • 1
Raedwald
  • 46,613
  • 43
  • 151
  • 237
  • Data class is sublcassed by java.sql.Date/Time/Timestamp, being final won't help as it has setter methods. Actually being non-final is good as you can override the setters and throw UnsupportedOperationException, making the class immutable. – bestsss Feb 06 '13 at 12:58
  • @bestsss "as it has setter methods": the point is, `Date` should not have setter methods. – Raedwald Feb 07 '13 at 13:02
  • 1
    the question is about being final, not about being immutable on its right own. When `Date` was firstly introduced, there was no Calendar and making it immutable later was no-go. So if you want immutable Date, just create one - i.e. make it final and forbid the setters. – bestsss Feb 07 '13 at 13:58
0

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. For instance java.util.String is final for that very reason. So are many others. Some classes w/ private c-tor are declared final (Math, StrictMath) but it doesn't matter in such a case.

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. 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().

bestsss
  • 11,796
  • 3
  • 53
  • 63
0

I believe java.util.Arrays and java.util.Collections should be declared 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.

Additionally, java.lang.Math (another so-called utility class) has the same structure and it is also declared final.

Marco
  • 479
  • 4
  • 10
-2

Check the String class which is final and probably should had been your answer in the interview.

Check the docs.

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

Afshin Moazami
  • 2,092
  • 5
  • 33
  • 55
Serdar Dogruyol
  • 5,147
  • 3
  • 24
  • 32