4

This question discusses the practices of non-static final variables.

My first impression is that non-static final variables are useless because final variables cannot be reassigned after initialization.

class Foo {
    public static final int BAR = 10;
}

That would mean all the objects created from type Foo would have BAR = 10.

When would it be useful, practical, or accepted to use non static, but final variables, like so?

class Foo {
    public final int BAR = 10;
}

So in what case does the latter become useful? Since it basically means the same thing.

EDToaster
  • 3,160
  • 3
  • 16
  • 25
  • If you set it in the ctor. – SLaks Sep 07 '14 at 22:16
  • *“with the final modifier on a variable, nothing can change it after initialization, right?”* – In your example, yes. However, be aware not to confuse `final` in Java with `const` in C++. If it is not a primitive type but a class that carries state which can be altered by public methods, then that state can be changed even if the variable is declared `final`. – 5gon12eder Sep 07 '14 at 22:25
  • @JClassic [did so](http://stackoverflow.com/a/25715922/1392132) – 5gon12eder Sep 08 '14 at 00:08

4 Answers4

6

When that same animal has a field like this:

private final Animal mother;

Everyone only has one biological mother and there is no shared mom, meaning it is specific for each instance.

Making it static means that the value is shared amongst all instances. If this is what you want then it makes sense ofcourse.

Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
6

final in Java is not to be confused with const in C++. Declaring a variable final means that it cannot be reassigned. If the variable is a primitive type, this is fine. If the variable is a reference type, declaring it final does not prevent it from mutating.

This is safe (as int is a primitive type) and commonly accepted:

class Week {
    public static final int NUMBER_OF_DAYS = 7;
}

Week.NUMBER_OF_DAYS = 6;  // error: cannot reassign final variable

This is also safe. While java.lang.String is not a primitive type, it is guaranteed to be immutable. (Ie String has no method that changes its value and it must never get one or a quite fundamental language-level contract will be broken.) I still find that many people dislike this use of public attributes and many style guides ban it.

class Weekday {
    public final String name;

    public Weekday(String name) {
        this.name = name;
    }
}

Weekday monday = new Weekday("Monday");
monday.name = "Tuesday";  // error: cannot reassign final variable

This is not safe:

class Week {
    public static final String[] DAYS_OF_THE_WEEK = {
      "Monday",
      "Tuesday",
      "Wednesday",
      "Thursday",
      "Friday",
      "Saturday",
      "Sunday",
    };
}

Week.DAYS_OF_THE_WEEK = new String[6];  // error: cannot reassign final variable
Week.DAYS_OF_THE_WEEK[2] = "February";  // this is not prevented!

Using a java.util.Collection would not have made the last example much better. There are Collections that amputate all mutating methods but the only thing this will buy us is a run-time error. The compiler can't help here.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
2

A common use case for this is lock objects.

private final Object lock = new Object();
...
synchronized(lock) {...}

This pattern some times requires that the lock object belong to the instance and not to the class (static).

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
0

If the field type is immutable, then it only makes sense if it's a value assigned by a constructor.

final class Point {
    final double x, y;
    Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

If the field's value is mutable, then it does make sense to have a final field initialized at its declaration site, because each instance will get its own reference.

final class ListWrapper<A> {
    final List<A> list = new ArrayList<>();
}

But in the example you gave, no, it never makes sense to initialize a field as public final int SIZE = 10;.

Chris Martin
  • 30,334
  • 10
  • 78
  • 137