简体   繁体   English

在Java构造函数中初始化最终变量

[英]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抱怨a和b属性? Idea underline them and say: Variable a might not have been initialized. Idea在其下划线并说:变量a可能尚未初始化。 I am sure that I have no more constructors and that in every case a will be populated with some value. 我确信不再有构造函数,并且在每种情况下a都将填充一些值。

I don't really know how to properly answer the why (JLS investigation needed), but for the how , the following should compile: 我真的不知道如何正确回答“ 为什么” (需要进行JLS调查),但是对于“ 如何” ,应编译以下内容:

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;
}

As per the JLS specs http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.2 根据JLS规范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; 必须在声明该类的每个构造函数(第8.8节)的末尾明确分配一个空白的最终实例变量(第16.9节); otherwise a compile-time error occurs. 否则会发生编译时错误。 This is why Idea is complaining. 这就是为什么Idea抱怨的原因。

What about the case where the constructor that takes no arguments is called, c is the only object variable that's being initialized. 如果调用不带任何参数的构造函数,那么c是唯一要初始化的对象变量。 The object variables a and b only get initialized in the constructors that take arguments. 对象变量a和b仅在带有参数的构造函数中初始化。 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;
}

As mentioned in the other answers, after leaving a constructor your final fields must be initialized. 如其他答案中所述,离开构造函数后,必须初始化final字段。 Hence provide one constructor which initializes all fields and reuse it by the public constructors to provide the concrete values. 因此,提供一个初始化所有字段的构造函数,并由public构造函数重用它以提供具体的值。 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);
}

As Jeremy already said in comment, there could be some code that calls the private constructor instead of the intended public ones. 正如杰里米(Jeremy)在评论中所说,可能会有一些代码调用private构造函数而不是预期的public

Concerning the fix, I prefer a pattern where 1 (private?) constructor sets all variables, and other additional constructors call this "main" constructor, eg: 关于此修复程序,我更喜欢一种模式,其中1(私有?)构造函数设置所有变量,而其他附加的构造函数将其称为“主要”构造函数,例如:

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);
}

In java all the final field must be initialize to some value. 在Java中,所有final字段都必须初始化为某个值。 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. 如果某个最终字段未使用声明进行初始化,则应在所有构造函数中对其进行初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM