2016-07-27 181 views
15

我遇到一个问题,询问 “关于”默认“构造函数,下列哪一项是正确的?”默认构造函数不初始化类的实例成员?

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

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

Class Test { 
     String name; 
    } 

那么编译器创建默认构造函数,看起来像

Class Test { 
     String name; 
     Test(){ 
      super(); 
      name = null; 
     } 
    } 

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

+1

[Java默认构造函数]的可能重复(http://stackoverflow.com/questions/4488716/java-default-constructor) –

+2

'class'在Java中是小写的。 – kamoroso94

回答

9

类构造函数不是初始化的类,JVM执行此操作。在创建对象的内存之后,该对象的成员默认初始化为某个可预测的值,这成为其默认值。

按照specification

  • 每个类变量,实例变量,或阵列组分与默认值进行初始化,创建(§15.9§15.10.2),当它:
    • 对于类型字节,默认值为零,即(byte)0的值。
    • 对于short类型,默认值为零,即值为(short)0
    • 对于int类型,默认值为零,即0
    • 对于long类型,默认值为零,即0L
    • 对于浮点类型,默认值为正零,即0.0f
    • 对于double类型,默认值为正零,即0.0d
    • 对于char类型,默认值为空字符,即'\u0000'
    • 对于布尔类型,默认值为false
    • 对于所有参考类型(§4.3),默认值为null

你的假设是接近,但事实是,之前的构造函数的参数甚至评估 - 才可以值甚至分配给每个字段的 - 这些领域已经持有其默认值,并这由JVM完成。

阅读款§15.9.4了解初始化过程是如何进行的

+0

这是否意味着对于编写良好的非默认构造函数,您的成员会被初始化,然后立即再次更改其值?看起来效率不高。 –

+0

@LightnessRacesinOrbit并非所有的非默认构造函数都会初始化所有成员。 _写作_是一个有趣的财产来尝试和评估。 – Gusdor

+0

@LightnessRacesinOrbit:我只为一个Java实现做出了贡献,那是多年前的事情,但我们这样做的方式是分配零编码内存(并且IIRC将gc归零内存销毁)。所以是的,从某种意义上说,与C或C++相比,效率低下,其中存在未初始化的内存。你所付出的是,Java中没有这样的东西。但是,它并没有像将'0'明确地分配给即将被覆盖的'byte'数据成员那样糟糕。它全部是'memset',通常在低优先级的线程中。我不知道Oracle是否以同样的方式做到这一点。 –

1

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

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

即0 INT,空为引用类型..等

然而,值得注意的是,我们不应该想当然地认为一个默认值,并给出选择不初始化的变量。


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

3

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

没有,构造函数被调用毕竟实例变量是由默认值初始化:0primitive numerical typesfalsereference types同等价值的boolean类型,null

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

-1这不能证明任何东西。作为隐含的'super()',可以在构造函数的开始处编译初始化。 –

+0

实际上,你展示了一个不同的东西:你展示的初始化实际上移动到了类的初始化块中,在初始化所有参数初始化之后执行初始化块(在为对象分配内存之后由JVM完成)在完成这两个之后,构造函数被调用。 – Falco

+0

'myField','initMyField'。请注意lowerCase。 – glglgl

0

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

class DefaultTest{ 
int id; 
String name; 

void display(){System.out.println(id+" "+name);} 

public static void main(String args[]){ 
DefaultTest s1=new DefaultTest(); 
DefaultTest s2=new DefaultTest(); 
s1.display(); 
s2.display(); 
} 
} 

NB:由于没有构造中定义的编译器将生成一个默认的构造将分配0空值的两个对象。

-1

不,它不会初始化非原始实例变量。 只有一个原始的get初始化与默认值

Integer nonPrim; 
int prim; 

然后创建对象后nonPrim == null; prim == 0

感谢

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 
0

每当我们正在执行的Java类,第一静态控制流将被执行。在静态控制流,如果我们正在创建一个对象,然后作为Inatance控制流的一部分的下面的步骤将被执行(在所提到的顺序):

  1. 从实例成员(实例变量和实例块)的鉴定从上到下。
  2. 执行实例变量赋值和实例块。
  3. 执行构造函数。

因此,在上面的代码中,即使在执行构造函数之前,实例变量“name”已经被分配给null(引用类型的默认值)。

相关问题