需要在Java中初始化参数化构造函数中的最终引用

时间:2011-10-27 21:14:51

标签: java

import java.util.*;

public Class C
{
     final Vector v;
     C()
     {
          v=new Vector();
     }

     C(int i)
     {
          //Here, it is an error. v might not have been initialized.
     }

     public void someMethod()
     {
           System.out.println(v.isEmpty());
     }

     public static void main(String[] args)
     {
          C c=new C();
          c.someMethod();
     }
} 

上面的代码是编译时错误。我知道,但它说(在NetBeans中)变量v应该被初始化。当我在重载的构造函数中初始化它时,它修复了问题并打印“true”。我的问题是为什么我应该在重载版本的构造函数中再次初始化它。(我已经在默认构造函数中初始化了一次)并且我甚至没有使用重载版本。为什么呢?

3 个答案:

答案 0 :(得分:5)

因为重载的构造函数没有调用默认构造函数。

使用this()来调用它。

答案 1 :(得分:4)

创建新对象时,只调用类的一个构造函数来初始化对象。您似乎认为所有构造函数都被调用,或者始终调用默认(无参数)构造函数。事实并非如此。

因此,每个构造函数都需要初始化所有final成员变量。

请注意,从一个构造函数中,您可以使用this(...)显式调用另一个构造函数。例如,作为C(int i)构造函数的第一行,您可以添加一行:this();来调用C()构造函数。另一种解决方案是在您声明它的行初始化成员变量:

public class C {
    // v will be initialized, no matter which constructor will be used
    final Vector v = new Vector();

    C() {
    }

    C(int i) {
        // ...
    }

    // ... etc.
}

请注意,您不需要显式初始化非final成员变量;如果不初始化它们,Java将使用默认值(对于非基本类型变量为null)初始化它们。但是,您需要显式初始化final成员变量。

另一个注意事项:Vector是遗留的集合类。您应该更喜欢使用ArrayList

第三个注意事项:使用泛型使您的代码更加类型安全。例如,如果您需要在列表中存储字符串,请使用ArrayList<String>而不是原始类型ArrayList

答案 2 :(得分:1)

重载的构造函数不会调用其他版本,除非您使用

明确地执行此操作
this();

这可能就是你想做的事。