2013-02-25 109 views
3

以下两点之间有什么区别,哪个更好?构造函数声明和初始化的初始化之间的区别

public class foo { 

    int i = 2; 

} 

public class foo { 

    int i; 
    foo() { 

     i = 2; 

    } 
} 
+0

考虑纠正你的例子中的错误,因为它不能反映你的问题标题。 – Perception 2013-02-25 11:32:18

+0

对不起。刚纠正了错误。 – user1976547 2013-02-25 11:37:22

+0

如果您使用的是对象类型而不是使用基本类型,那么如果您在声明时初始化该变量,如果在变量初始化时发生异常,您该怎么办?使用构造函数,这就是为什么他们被发明。如果您必须初始化不需要参数的变量,请将它们放入您的无参数构造函数中。如果你要添加额外的参数构造函数,然后链接被称为“伸缩构造函数”的构造函数,所以你不必重复你的代码。 – 2016-05-09 03:07:01

回答

1

如果有两个或更多的建设者和intialization值在他们每个人的不同,那么你应该使用构造函数初始化,因为没有办法做到与成员初始化一样...

然而

如果你只有一个构造函数...你可以使用成员初始化来获得更好的代码清晰度。

+0

是的。这是一个错误 – user1976547 2013-02-25 11:39:56

+0

@ user1976547鉴于与纠正的代码 – MayurB 2013-02-25 11:42:24

+0

@MayurB答案我给了相同的初始响应,但OP已经修改了现在的代码,所以实际上我都作为一个伊娃。可能要重写或删除以避免下传。 – wmorrison365 2013-02-25 12:05:46

0

在你的第一个例子中,我是foo类的一个实例变量(更好的名字是Foo)。它在加载类时被初始化。

在你的第二个例子中,我是也是一个实例变化,但在这种情况下,在foo()构造函数中初始化。

这里没有真正的区别,特别是对于基元。但是,在多线程环境中,如果您打算在构造函数中初始化您的ivars,并且这些ivars是非原始的,则需要避免暴露部分构造的对象的风险。原因是构造函数不同步,不能应用synchronised关键字,但是两个线程不能构造同一个对象。

所以,为了避免这种情况,你不应该在构造函数中暴露this。这样做的一种方法是调用非最终方法。这样做,比如说调用一个抽象方法,可以让一些未知的代码对未完成的对象做些什么。显然,如果你在你的声明中初始化,这是无法完成的。

p.s.我以为有效的Java有什么,但找不到任何东西。所有的

+0

呃...为什么downvote?至少留下什么是错误的评论。 – wmorrison365 2013-02-25 11:34:53

+0

你在哪里看到'local variable'?这是不正确的。 – Andremoniy 2013-02-25 11:35:25

+0

我的不好。刚刚编辑了代码。 – user1976547 2013-02-25 11:35:59

0

首先,我觉得第二个例子应该是这样的:

public class foo{ 

    int i; 
    foo(){ 

    i = 0; 

    } 

} 

否则我只是在C'tor范围的局部变量。其次,第一个例子显示了在类C'tor被调用之前调用的初始化。如果您希望这种情况发生,无论使用什么C'tor,这都很好。 它还使您能够将我声明为只读。

0

特别是这种情况下,这两个变体没有区别。第一种变体是更可取的,因为像往常一样,构造函数中的字段的初始化使用来自构造函数参数的外部值。

2

在你的例子中,行为语义没有区别。在Java中,所有实例字段初始值设定项(和实例块)都是在超类初始化之后执行,而之前是构造函数的主体;见JLS 12.5

区别在于代码可读性和(在其他示例中)避免重复编码和易碎性。这些需要根据具体情况进行评估。

还值得注意的是,有些情况下你必须在构造函数中初始化;即当初始化依赖于构造函数参数。


1 - 重复性和脆弱性问题是同一事物的反面。如果你有多个构造函数,“在构造函数中初始化”的方法往往会导致重复。如果添加额外的字段,则可以将初始化添加到所有相关的构造函数中;即脆弱性。

+0

+1。你可能想提供一些背景知识,为什么***这两个在功能上是相同的,可能是通过说明类的初始化过程。 – Perception 2013-02-25 11:57:19