1

Why isn't Java allowing me to initialize final variables indirectly? I don't see why it shouldn't work, I mean the method will always run so what difference does it make if initialized directly or via method?

This code works:

package com.company;

public class Person {

    private final String name;

    public Person() {
        name = "bob";
    }
}

This one doesn't. (even if I get rid of IO code and hardcode the value assigned to name)

package com.company;

import java.util.Scanner;

public class Person {

    private final String name;

    public Person() {
        askName();
    }

    public void askName() {
        Scanner scanner = new Scanner(System.in);
        name = scanner.nextLine();
    }
}
  • 2
    Well, `final` means, you cannot assign to it except in a constructor or at the point of declaration. – Henry Oct 03 '18 at 13:38
  • Possible duplicate of [How does the "final" keyword in Java work? (I can still modify an object.)](https://stackoverflow.com/questions/15655012/how-does-the-final-keyword-in-java-work-i-can-still-modify-an-object) – Irshad Ahmed Akhonzada Oct 03 '18 at 13:38

5 Answers5

4

This is common sense. You can only initialize a final variable once.

A constructor can only be called once, so, unless the variable is static, it can be initialized here.

But your method can be called unlimited times, which would cause the variable to be re-referenced, which is just what the final keyword is supposed to avoid of happening.

Stultuske
  • 9,296
  • 1
  • 25
  • 37
  • that actually makes sense. It would be nice to be possible to encapsulate long pieces of code in the constructor into a function but that would be the sole purpose of the function. – cellpowerhouse Oct 03 '18 at 13:48
4

final fields must be set in the constructor. What you can do is the following.

import java.util.Scanner;

public class Person {

    private final String name;

    public Person() {
        name = askName();
    }

    public static String askName() {
        Scanner scanner = new Scanner(System.in);
        return scanner.nextLine();
    }
}

However, a better option is likely to inject the value you need.

import java.util.Scanner;

public class Person {

    private final String name;

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

    public static Person askName() {
        Scanner scanner = new Scanner(System.in);
        return new Person(scanner.nextLine());
    }
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
3

You can assign values to final member variables in 4 places only:

  1. At the point of declaration

  2. In the constructor

  3. In a static initialization block (if the variable is static)

  4. In a initialization block (if the variable is not static)

ACV
  • 9,964
  • 5
  • 76
  • 81
0

You can initialize final variable at 4 places.

  • with declaration
  • in constructor (only non-static)
  • in static initializer (for only static)
  • in instance initializer (only non-static)

static final variable

These variables can be initialized in either the declaration or static initializer.

class Program {
    static final int i1 = 10;
    static final int i2;
    static {
        i2 = 10;
    }
}

final variable

final variables can be initialized in the declaration, instance initializer, or constructor:

class Program {
    final int i1 = 10;
    final int i2;
    final int i3;
    {
        i2 = 10;
    }

    Program() {
        i3 = 10;
    }
}

Local final variables

These variables can be initialized in the declaration or any place after its declaration. The local final variables must be initialized before they are used.

class Program {
    void method() {
         final int i1 = 10;
         final int i2;
         System.out.println(i1);
         i2 = 10;
         System.out.println(i2);
         return ;
    }
}
Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212
0

It is because final variables cannot be initialized in a method. It needs to be initialized in constructor ,while declaring only or in static blocks only.

codeLover
  • 2,571
  • 1
  • 11
  • 27