在java构造函数中初始化final变量

时间:2017-03-21 12:06:12

标签: java data-structures

假设我有这样的情况。

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

为什么Idea会抱怨a和b属性? Idea强调它们并说:变量a可能尚未初始化。我确信我没有更多的构造函数,并且在每种情况下都会填充一些值。

6 个答案:

答案 0 :(得分:2)

我真的不知道如何正确回答为什么(需要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;
}

答案 1 :(得分:2)

根据JLS规范 http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.2

必须在声明它的类的每个构造函数(第8.8节)的末尾明确赋值空白的最终实例变量(第16.9节);否则会发生编译时错误。 这就是Idea抱怨的原因。

答案 2 :(得分:0)

如果调用不带参数的构造函数,c是唯一被初始化的对象变量。对象变量a和b仅在带参数的构造函数中初始化。所以修复应该如下?

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

答案 3 :(得分:0)

如其他答案所述,离开构造函数后,必须初始化最终字段。因此,提供一个构造函数来初始化所有字段并由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); } 构造函数重用它以提供具体值。喜欢这段代码:

-- temporary table like your data ------------
DECLARE @account_fans TABLE(brand NVARCHAR(10),account NVARCHAR(10),fans INT)
INSERT INTO @account_fans VALUES ('Ford', 'ford_uk',10),('Ford', 'ford_uk',11),
('Ford', 'ford_us',20),('Ford', 'ford_us',21),('Jeep', 'jeep_uk',30),
('Jeep', 'jeep_uk',31),('Jeep', 'jeep_us',40),('Jeep', 'jeep_us',41)
-- temporary table like your data ------------

SELECT * FROM @account_fans -- your table 


SELECT brand, SUM(fans) fans FROM ( 
SELECT brand,account,MAX(fans) fans FROM @account_fans GROUP BY account,brand 
) A GROUP BY brand -- output you require

答案 4 :(得分:0)

正如Jeremy在评论中所说,可能会有一些代码调用private构造函数而不是预期的public构造函数。

关于修复,我更喜欢一种模式,其中1(private?)构造函数设置所有变量,而其他附加构造函数调用此“main”构造函数,例如:

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

答案 5 :(得分:0)

在java中,所有final字段必须初始化为某个值。它们只能在声明它们的位置或构造函数中赋值一次。 如果某些final字段未使用声明进行初始化,那么它应该在所有构造函数中初始化。