Tuesday, August 26, 2014

final Keyword in Java

I like the "final" keyword in Java. However, I'd like it more if every reference were final by default and "muttable" was a the keyword to create a mutable a reference. This way around is better because if you see "mutable" in a reference declaration then you know that the author took the time to do that because they are mutating the reference. Mutation is the case you want to watch out for and discourage. Today, if a reference isn't marked as final you don't know if that means it's mutated or if the programmer isn't using final. In my experience mutability is the rarity and final is the common case.

Unlike C++, Java doesn't have a way of making both the reference and object constant. In java the declaration.

public class Foo {
    private final Date someDate = new Date();

// ....

Doesn't stop you from mutating the object like this:

    someDate.setTime(1234); 

It just stops you from changing the reference like this:

    someDate = new Date(); // not allowed, referenced is final

Some programmers use the final keyword to mean that not only shouldn't the reference change but the object shouldn't either. Restricting final in this way is not a good idea. Basically, that's not what final means and if you do that you're not helping anything.

I am generally against using language keywords like final to mean something other than what the compiler can assert from them. Marking a reference final doesn't guarantee that the object won't change. You might as well add a comment to the declaration like this:

public class Foo {
    // someDate is not mutated
    private final Date someDate = new Date();

// ....

Because it has about the same chance of either being honoured or going out of date.

Additionally, knowing that the reference is final (not the object) is still very useful on its own. This is why C++ has the ability to make both the object and reference constant independently. By using final to mean the object and reference shouldn't change you confuse maintainers with an idiosyncratic style and destroy the utility of final-for-references-only.

If you want to create an object that doesn't change then create an immutable object. (see the link)

I have to say that I personally don't make function parameters final because it's too much bother. I've found it looks like noise in the code and other developers resent it. Instead I have the compiler warn me if there's any assignment to a method parameter, which accomplishes the same thing.

If you are using eclipse you can turn that on by going to Window -> Preferences -> Java -> Compiler -> Errors/Warnings and turning on the "Code Style -> Parameter Assignment" warning. Go ahead, make it an "Error" if you dare.

Marking an object's members as final is much more useful. I've always though of object members as mini-global variables. Global variables are bad but global constants are less so. When followed religiously, it allows the maintainer to see at a glance which references are being mutated or ideally that non are. When combined with extensive use of immutable objects it also allows you to quickly see what is being mutated if anything.

While I don't bother marking method parameters final, I try and mark every class and object member I can as final. I've gone so far as to re-write code to mark more members final. I find it helps me understand my code and code of others faster than if I didn't and avoid errors too.

No comments: