Spasoje Petronijević
Spasoje Petronijević

Reputation: 1608

Initializing final variable in java constructor

Lets say I have a situation like this.

private final A a;
private final B b;
private final C c;
private ClassX(){
  this.c = createCSomehow();
}
public ClassX(A a){
  this();
  this.a = a;
  this.b = null;
}
public ClassX(B b) {
  this();
  this.b = b;
  this.a = null;
}

Why Idea is complaining about a and b property? Idea underline them and say: Variable a might not have been initialized. I am sure that I have no more constructors and that in every case a will be populated with some value.

Upvotes: 2

Views: 16302

Answers (6)

sandeep garg
sandeep garg

Reputation: 23

In java all the final field must be initialize to some value. They can be assign value only once either where they are declared or in the constructor. If some final field is not initialize with declaration then it should be initialize in the all the constructor.

Upvotes: 1

Harmlezz
Harmlezz

Reputation: 8078

As mentioned in the other answers, after leaving a constructor your final fields must be initialized. Hence provide one constructor which initializes all fields and reuse it by the public constructors to provide the concrete values. Like this code:

private ClassX(A a, B b) {
    this.a = a;
    this.b = b;
    this.c = createCSomehow();
}

public ClassX(A a){
  this(a, null);
}

public ClassX(B b) {
    this(null, b);
}

Upvotes: 1

radoh
radoh

Reputation: 4825

As Jeremy already said in comment, there could be some code that calls the private constructor instead of the intended public ones.

Concerning the fix, I prefer a pattern where 1 (private?) constructor sets all variables, and other additional constructors call this "main" constructor, e.g.:

private ClassX(A a, B b){
  this.a = a;
  this.b = b;
  this.c = createCSomehow();
}
public ClassX(A a){
  this(a, null);
}
public ClassX(B b) {
  this(null, b);
}

Upvotes: 1

avlec
avlec

Reputation: 394

What about the case where the constructor that takes no arguments is called, c is the only object variable that's being initialized. The object variables a and b only get initialized in the constructors that take arguments. So the fix should be as follows?

final A a;
final B b;
final C c = createCSomehow();

public ClassX() {
    a = null;
    b = null;
}

public ClassX(A a) {
    this.a = a;
    b = null;
}

public ClassX(B b) {
    a = null;
    this.b = b;
}

Upvotes: 0

Jason1
Jason1

Reputation: 111

As per the JLS specs http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.2

A blank final instance variable must be definitely assigned (§16.9) at the end of every constructor (§8.8) of the class in which it is declared; otherwise a compile-time error occurs. This is why Idea is complaining.

Upvotes: 6

sp00m
sp00m

Reputation: 48837

I don't really know how to properly answer the why (JLS investigation needed), but for the how, the following should compile:

private final A a;
private final B b;
private final C c = createCSomehow();

public Main(A a){
  this.a = a;
  this.b = null;
}

public Main(B b) {
  this.b = b;
  this.a = null;
}

Upvotes: 6

Related Questions