2013-07-24 57 views
4

当我定义的Java类:如何初始化实例成员?

class A { 
    private String str = "init method 1"; 

    public A() { 
     str = "init method 2"; 
    } 
} 

我既可以初始化str,当把它定义或init它的构造函数。我的问题是两种方法有什么区别?哪种方法是首选?

+0

你在谈论实例成员(类成员将是'静态')。请注意,您的问题没有单一的正确答案,所以答案将基于意见。 –

+1

另外检查这个问题:http://stackoverflow.com/questions/3918578/should-i-initialize-variable-within-constructor-or-outside-constructor – Yuri

回答

4

初始化块值在构造函数分配给它们之前分配。

因此,值init member 1将首先分配,然后init member 2将被分配。

考虑从theJavaGeek

class InitBlocksDemo { 

    private String name ; 

    InitBlocksDemo(int x) { 
     System.out.println("In 1 argument constructor, name = " + this.name); 
    } 

    InitBlocksDemo() { 
     name = "prasad"; 
     System.out.println("In no argument constructor, name = " + this.name); 

    } 

    /* First static initialization block */ 
    static { 
     System.out.println("In first static init block "); 
    } 

    /* First instance initialization block */ 
    { 
     System.out.println("In first instance init block, name = " + this.name); 
    } 

    /* Second instance initialization block */ 
    { 
     System.out.println("In second instance init block, name = " + this.name); 
    } 

    /* Second static initialization block */ 
    static { 
     System.out.println("In second static int block "); 
    } 

    public static void main(String args[]) { 
     new InitBlocksDemo(); 
     new InitBlocksDemo(); 
     new InitBlocksDemo(7); 
    } 

} 

此输出这个例子中,如下

In first static init block 
In second static int block 
In first instance init block, name = null 
In second instance init block, name = null 
In no argument constructor, name = prasad 
In first instance init block, name = null 
In second instance init block, name = null 
In no argument constructor, name = prasad 
In first instance init block, name = null 
In second instance init block, name = null 
In 1 argument constructor, name = null 

程序流动。

  • 当程序开始执行时,类InitBlocksDemo被加载到JVM中。
  • 静态初始化块按照它们在程序中出现的顺序加载时运行。
  • 现在执行静态块时,遇到main方法。
  • 语句new InitBlocksDemo();导致无参数构造函数被调用。
  • 因为有一个默认调用super无参数的构造函数,就进入超类即Object
  • ,它已经完成后,再控制回来我们班,并开始给予默认值实例变量。在这种情况下,变量名将被赋值为null
  • 现在实例块将按它们在程序中出现的顺序执行。我们还没有重新赋值给变量名,所以它会打印null
  • 执行实例块后,控制权转到构造函数。这里name =“prasad”;将重新分配一个新值,因此“prasad”将打印在无参数构造函数中
  • 9.语句new InitBlocksDemo(7);导致调用单参数构造函数。其余的过程是相同的。唯一的区别是名称不重新分配一个新的值,因此它会打印null
3

不同之处在于分配发生时。

System.out.println(str); 

,你会看到你分配在构造函数中较新的一个以前的老值有: 字段构造函数运行之前,所以如果你加入这行到你的构造函数分配的常量值。

除了那个以外,没有什么区别,而且使用的主要是个人偏好。

个人anythiong我可以直接指定为字段声明的一部分 - 这就是我所做的。

3

他们之间没有什么区别,编译器副本初始化块建设者

如果,反编译生成的类文件的类

class A { 
    private String str1 = "init method 1"; 

    private String str2; 

    public A() { 
     str2 = "init method 2"; 
    } 

    public A(String str2) { 
     str2 = str2; 
    } 
} 

你可以找到

class A 
{ 

    private String str1; 
    private String str2; 

    public A() 
    { 
     str1 = "init method 1"; 
     str2 = "init method 2"; 
    } 

    public A(String str2) 
    { 
     str1 = "init method 1"; 
     str2 = str2; 
    } 
} 
1

在我的个人经验,它关于对象初始化的昂贵程度或详细程度。其次,你也可以把它看成是懒惰创造vs积极创造。如果只涉及构造函数,我通常会在实例变量级别创建对象。如果还有其他调用来初始化成员,那么调用肯定会被移到构造函数或需要初始化的方法中。

这就是为什么使用工厂方法模式来委托实际的对象创建到另一个类。