默认构造函数不初始化类的实例成员?

时间:2016-07-27 05:29:55

标签: java constructor default-constructor

我遇到了一个问题 “关于”默认“构造函数,以下哪一项是正确的?”

和一个选项 “它初始化了该类的实例成员。” 是不正确的选择。

现在我的理解是,如果我们有一个代码,如

    Class Test {
        String name;
    }

然后编译器创建看起来像

的默认构造函数
    Class Test {
        String name;
        Test(){
            super();
            name = null;
        }
    }

是不是默认构造函数初始化实例成员name = null?

7 个答案:

答案 0 :(得分:10)

类构造函数不是进行初始化的那个,JVM就是这样做的。创建对象的内存后,对象的成员将默认初始化为某个可预测的值,该值将成为其默认值。

根据specification

  
      
  • 每个类变量,实例变量或数组组件在创建时都使用默认值进行初始化(§15.9§15.10.2):      
        
    • 对于type byte,默认值为零,即(byte)0
    • 的值   
    • 对于type short,默认值为零,即(short)0
    • 的值   
    • 对于int类型,默认值为零,即0
    •   
    • 对于long类型,默认值为零,即0L
    •   
    • 对于float类型,默认值为正零,即0.0f
    •   
    • 对于double类型,默认值为正零,即0.0d
    •   
    • 对于char类型,默认值为空字符,即'\u0000'
    •   
    • 对于类型布尔值,默认值为false
    •   
    • 对于所有引用类型(§4.3),默认值为null
    •   
  •   

您的假设很接近但事实是,在构造函数参数被评估之前 - 甚至在为每个字段分配值之前 - 这些字段已经保持其默认值,这是由JVM完成的。 / p>

阅读第§15.9.4小节以了解如何执行初始化过程

答案 1 :(得分:4)

在Java字段中,在构造函数之前初始化。这可以通过以下代码轻松证明:

public class MyClass {

    int myField = initMyField();

    MyClass(){
        System.out.println("ctor");
    }

    static int initMyField() {
        System.out.println("init field");
        return 1;
    }
}

输出

init field
ctor

您还可以查看解压缩的代码。

答案 2 :(得分:3)

  

不是初始化实例成员name = null的默认构造函数吗?

不,构造函数在之后被调用所有实例变量被默认值0primitive numerical types的等效值false初始化为{ {1}} reference types输入boolean

答案 3 :(得分:1)

不,它不是为您初始化实例变量的默认构造函数。每种类型都有一个默认值。创建对象的那一刻,使用默认值。

因此,如果您没有显式初始化实例变量,它们仍然会隐式使用为它们定义的默认值。

即。 0表示int,null表示引用类型.. etc

但是,值得注意的是,我们不应该理所当然地认为给出了默认值,并选择不初始化变量。

您可以尝试定义一个空构造函数,该构造函数使用空实现覆盖默认构造函数。您将意识到所有实例变量仍将被初始化。

答案 4 :(得分:1)

确实如此。虽然问题更多地基于使用。

public class Main {
    String x;

    Main() {
        x = "Init";
    }

    @Override
    public String toString() {
        return x;

    }

    public static void main(String[] args) {
        System.out.println(new Main());
    }

}

输出继电器:

Init

答案 5 :(得分:0)

默认构造函数为对象提供默认值,并且通常在没有显式定义构造函数时由编译器创建。 e.g。

try
{
    conn.Open();
    SqlCommand cmd = new SqlCommand(sql, conn);
    SqlParameter[] pram = new SqlParameter[7];
    pram[0] = new SqlParameter("@fname", SqlDbType.VarChar, 50);
    pram[1] = new SqlParameter("@lname", SqlDbType.VarChar, 50);
    pram[2] = new SqlParameter("@dob", SqlDbType.VarChar, 50);
    pram[3] = new SqlParameter("@gender", SqlDbType.Char, 10);
    pram[4] = new SqlParameter("@fathername", SqlDbType.VarChar, 50);
    pram[5] = new SqlParameter("@contact", SqlDbType.Int, 100);
    pram[6] = new SqlParameter("@address", SqlDbType.VarChar, 50);

    pram[0].Value = fname;
    pram[1].Value = lname;
    pram[2].Value = dob;
    pram[3].Value = gender;
    pram[4].Value = fathername;
    pram[5].Value = contact;
    pram[6].Value = address;

    for (int i = 0; i < pram.Length; i++)
    {
        cmd.Parameters.Add(pram[i]);
    }
    cmd.CommandType = CommandType.Text;
    cmd.ExecuteNonQuery();
}
catch(System.Data.SqlClient.SqlException ex_msg)
{
    string msg = "Error occured while inserting";
    msg += ex_msg.Message;
    throw new Exception(msg);
}
finally
{
    conn.Close();
}

注意:没有定义构造函数,编译器将生成一个默认构造函数,该构造函数将为这两个对象分配0个空值。

答案 6 :(得分:0)

每当我们执行java类时,都会执行第一个静态控制流程。在静态控制流程中,如果我们正在创建一个对象,那么将执行以下步骤(按照上述顺序)作为Inatance Control Flow的一部分:

  1. 从上到下识别实例成员(实例变量和实例块)。
  2. 执行实例变量赋值和实例块。
  3. 构造函数的执行。
  4. 因此,在上面的代码中,即使在执行构造函数之前,实例变量“name”也已经被赋值为null(引用类型的默认值)。