0

Final variables. I have read everything I could find on it on this site, and others, and I almost understand them, but I'm still a bit confused.

So, I know the official answer for why we would declare a variable as final: it locks the variable and prevents it from being re-initialized. My questions are these:

  1. If it can't be re-initialized, it's value can still change right? For example:

    final int a = 1;
    a = a + 1;
    

    Would that kind of code still work, or would the "final int a" be locked with a value of 1 forever?

  2. If the value of int a above can still be changed even after declaring it as final, what is the point of final?

I guess question 2 is my biggest one. I keep seeing all these explanations about how it locks a variable, and some people even saying that they declare most of their variables as final, but the motivation behind doing so just doesn't make sense to me.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
craigmiller160
  • 5,751
  • 9
  • 41
  • 75

3 Answers3

4
final int a = 1; 
a = a + 1;

No, this code won't pass compilation, since it attempts to assign a new value to a final variable.

If, however, the type of a was a reference type of some mutable class, you would be able to mutate the state of the object. For example :

final StringBuidler a = new StringBuilder (20);
a.append ("foo");

The finality of the variable only prevents you from changing its value. If the final variable refers to an object whose state can be modified, the finality doesn't prevent you from modifying that state.

Eran
  • 387,369
  • 54
  • 702
  • 768
2

If you declare

final int a = 1;

then the following would cause a compile error because you declared as final but you're trying to reassign a variable to it:

a = a + 1;

However if you had an object called MyInt defined like so:

class MyInt{
    int myInt = 5;

    public int getInt() {
        return myInt;
    }

    public void setInt(int newInt) {
        myInt = newInt;
    }
}

and then you did this:

final MyInt bestIntEver = new MyInt();

you could still call

bestIntEver.setInt(42);

because the reference to bestIntEver isn't changing, but

bestIntEver = new MyInt();

would cause a compile error because you're changing the reference to that variable you declared as final.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Andrew Orobator
  • 7,978
  • 3
  • 36
  • 36
0

final means the value of a won't change. But, depending on type, the value of a might actually be the address of an object (in the question it was just an int so value was not an address, just a 1). Locking down the address a holds doesn't lock down the object. Designing the object to be immutable will.

Favorite metaphor for this is a briefcase with a 1 in it. An immutable design will lock the briefcase so people can't get inside and change the 1. final will handcuff it to your wrist so people can't slip you a new briefcase with something else in it. You need both if you want to be sure nothing can happen to your 1.

But that just goes for objects.

If you're a primitive (like int) there is no briefcase. You are not holding it's handle (address). You're just holding the 1 in your hand.

If you're a final primitive the 1 has been fused to your hand. You can't let go. You can't pick up anything else.

Object or primitive, what final means is the same. Whatever you hold, an address or a value, you hold it until you die.

If the value of int a above can still be changed even after declaring it as final, what is the point of final?

It can't.

...they declare most of their variables as final, but the motivation behind doing so just doesn't make sense to me.

Calling an identifier a variable when it's been declared final is really just a common bad habit. If it's final, it's not variable. It doesn't change. It's a constant.

There are a few motivations for creating constants. Semantic correctness is one. pi is a constant (3.14159...) so it doesn't make sense to go changing it's value. Another motivation is to protect against mistakes that cause bugs. Variables are often reused and so assigned new values. A constant is protected from unintended changes. The more you can protect against bad code the better.

Community
  • 1
  • 1
candied_orange
  • 7,036
  • 2
  • 28
  • 62