1

I was preparing for Java OCA certification where I came across a similar question like that of the following one:

public class TestClass {
    final int i;

    public static void main(String[] args) {
        TestClass t = new TestClass();
        System.out.println(t.i);
    }
}

As per Java, the instance and static variables are given default values. Surprisingly, this was error that was shown in my console:

error: variable i not initialized in the default constructor final int i;

Why wasn't i assigned a default value above?

Andrew Li
  • 51,385
  • 12
  • 117
  • 139
scriobh
  • 778
  • 5
  • 20
  • what value would expect it to get? If a class has a final member, it has to be initialized in the constructor explicitly. – Arthur Cinader Apr 11 '17 at 20:16
  • 1
    Thought that it would display 0 as the default value of a variable of type int is 0. @ArthurCinader – scriobh Apr 11 '17 at 20:17

6 Answers6

2

Assigning default value to the final variable would defeat the entire purpose of making a variable final in the first place.
final would mean that you can't change the value once assigned. If a default value is given to final variable then you would never be able to set the value of the variable to something else (even for the first time).

RITZ XAVI
  • 3,351
  • 22
  • 32
2

It's defined this way in the Java Language Specification:

Chapter 16. Definite Assignment

Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.

[...]

For every access of a local variable or blank final field x, x must be definitely assigned before the access, or a compile-time error occurs.

Where the term "blank final field" refers to a final field with no value or initializer, and "definitely assigned" means that the field will be assigned to no matter what:

The idea behind definite assignment is that an assignment to the local variable or blank final field must occur on every possible execution path to the access. Similarly, the idea behind definite unassignment is that no other assignment to the blank final variable is permitted to occur on any possible execution path to an assignment.

Aside from throwing an error by specification, there's logical reasoning behind the decision. There's no point in having a default value for a blank final field. In your case, the blank final is an integer, and it would just be given 0 and you wouldn't be able to change it. What would the use of the variable be?

Also, if a final variable is not explicitly given a default value, why not initialize it in the first place? You can't reassign to it later since a default value would already be given, so why not initialize it now?

Community
  • 1
  • 1
Andrew Li
  • 51,385
  • 12
  • 117
  • 139
0

Standard integers default to zero, so what would be the point of creating a constant for the 0 literal integer? It serves no purpose, thus you must create a constant with a value during initialization.

Malik Brahimi
  • 15,933
  • 5
  • 33
  • 65
  • I wanted to check whether it displays the int's default value. but then i got this. – scriobh Apr 11 '17 at 20:19
  • Do you understand what I'm saying? A constant for zero completely defeats the purpose of a constant. We use constants for field widths, for spaces between game items in a grid, etc. Zero is just completely pointless. – Malik Brahimi Apr 11 '17 at 20:19
  • Constants don't have default values, I think you're missing the point. Because constants can't change value they need to be defined and declared simultaneously. – Malik Brahimi Apr 11 '17 at 20:21
  • That is exactly why there is no default value. Because a `0` or `""` etc, defeats the very purpose of a constant and therefore how would the compiler know what to default to? – Malik Brahimi Apr 11 '17 at 20:22
  • "A constant for zero completely defeats the purpose of a constant." Really? http://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html#ZERO – Lew Bloch Apr 11 '17 at 20:31
  • The question was about `final` member variables, not constants. – Lew Bloch Apr 12 '17 at 05:09
0

Why didn't it assign a default value in the above case ? Can anyone explain!

if a default value were to be provided then you wouldn't be able to change the value of it. when the final keyword is used with variables it means once the variable is assigned, it cannot be re-assigned.

Wikipedia:

A final variable can only be initialized once, either via an initializer or an assignment statement. It does not need to be initialized at the point of declaration: this is called a "blank final" variable. A blank final instance variable of a class must be definitely assigned in every constructor of the class in which it is declared; similarly, a blank final static variable must be definitely assigned in a static initializer of the class in which it is declared; otherwise, a compile-time error occurs in both cases. (Note: If the variable is a reference, this means that the variable cannot be re-bound to reference another object. But the object that it references is still mutable, if it was originally mutable.)

further reading:

Definite Assignment

Ousmane D.
  • 52,579
  • 8
  • 80
  • 117
0

Error message is misleading since it can be initialized with default value:

class FinalTest{
    final int x = printXAndInitializeIt();

    private int printXAndInitializeIt(){
        System.out.println("x before initialization = "+x);
        return 1;
    }

    public static void main(String[] args) {
        FinalTest ft = new FinalTest();
        System.out.println("x after initialization = "+ft.x);
    }
}

Output:

x before initialization = 0
x after initialization = 1

But even if there is default value final variable expects explicit initialization, since in most cases lack of initialization is caused by mistake. This error could be changed to warning, but I am guessing that Java designers though that "better safe than sorry".

Pshemo
  • 118,400
  • 24
  • 176
  • 257
  • 1
    Interesting quirk of initialization is that even non-`final` member variables get initialized twice if initialized explicitly, once to the default, and then to the explicit value. So `private int index = 0;` initializes the variable to zero twice. The JVM is forbidden to optimize that to once. – Lew Bloch Apr 11 '17 at 20:37
0

It's not that final fields aren't initialized to the default value — in fact they sort of are, though you'll only observe the fact if you're doing some silly stuff — but that you're required to explicitly initialize them exactly once (either as part of the declaration, or in an initializer block, or in every single constructor).

To understand the motivation for this, consider the following code:

public class Foo {
    private final int mValue;

    public Foo(final boolean shouldSet) {
        if (shouldSet) {
            mValue = 1;
        }
    }

    // ...
}

If the field weren't final, then the compiler would infer an implicit = 0 at the end of its declaration; but with a final field that's not always valid . . . and in the above example, the compiler can't even tell beforehand whether it will be valid or not. So the compiler sidesteps the issue by never inferring an implicit = 0, and requiring explicit initialization.

ruakh
  • 166,710
  • 24
  • 259
  • 294