为什么调用一个方法来设置变量比在构造函数中正常设置变量更好?

时间:2010-09-03 01:37:42

标签: java accessor

我在Java书中做了一个项目并遇到了这个代码示例。本书的作者说,不是直接在我的构造函数中初始化X和Y,而是可以调用类的setLocation()方法。不幸的是,我没有这本书了解为什么这更好的具体解释。我对Java不太熟悉但不仅仅是......直接分配值更简单而不用担心另一个函数调用?

//Point constructor, normal way of initializing variables

private double x;
private double y;

Point(double initial_x, double initial_y)
{
 this.x = initial_x;   
 this.y = initial_y;
} 

//Point constructor, the other way

Point(double initial_x, double initial_y)
{ 
   setLocation(initial_x, initial_y);
} 


public void setLocation(double newX, double newY)
{
   this.x = newX;
   this.y = newY; 
}

7 个答案:

答案 0 :(得分:6)

我实际上建议不要在构造函数中调用setter,因为从构造函数中调用可覆盖的方法是个坏主意。此外,getter / setter的常见理由是逻辑可能会发生变化,您无需更改访问属性的所有人。但是,在这种情况下,如果逻辑发生变化,则必要的更改仅限于同一类。

答案 1 :(得分:2)

与上面所说的其他人一样,还有一个警告:

如果你因为并发或其他原因需要不可变对象,我可以看到反对这种做法的论据。如果您正在做多个线程可能对此对象起作用的任何事情,那么setter可能会让您遇到麻烦。

答案 2 :(得分:1)

因为两个实例变量都是私有的,所以在这个上下文中setLocation()的目的似乎是允许其他类修改Point对象的坐标,之后它已被初始化。而且由于构造函数可以有效地完成同样的事情(仅仅是为了这个简单的例子),构造函数只是为了简单起见而调用该方法。

答案 3 :(得分:0)

您可以更好地控制何时设置。

答案 4 :(得分:0)

如果在设置成员时涉及某些逻辑,并且您的类是可变的(提供的行为类似于第二次调用构造函数),那么使用初始化方法是有意义的。

private int width;
private int height;
private double diagonal;

Image(int initial_w, int initial_h)
{
 Init(initial_w, initial_h)
}

public void Init(int initial_w, initial_h)
{
 width = initial_w;
 height = initial.h
 diagonal = Math.sqrt(width*width + height*height); // constructor doesn't need to repeat this line
}

答案 5 :(得分:0)

如果xy是可变的并且具有非平凡的setter,那么使用setter初始化它们,即使在构造函数中也可以帮助避免重复代码。在这种情况下,您可能希望将setter标记为final,以防止派生类重写这些方法并导致构造函数出现意外行为。

如果setter是微不足道的(没有其他代码的简单赋值)那么在构造函数中使用setter的理由就不多了。

如果变量是不可变的,那么最好不要使用setter并直接在构造函数中初始化它们。

答案 6 :(得分:-1)

此资源可能有所帮助:

http://en.wikipedia.org/wiki/JavaBean

我个人发现,使用无参数构造函数可以简化依赖注入。例如使用Spring IoC,虽然你当然可以指定构造函数args,但它不需要更简单。

此外,我发现编写单元测试更简单,原因相同,即您可以实例化所需的对象,为测试目的注入所需的属性,然后进行测试。因此,使用带有args的构造函数可能需要您使用对测试不特别感兴趣的对象进行设置。

也就是说,提供一个无参数构造函数并不是为了方便的构造函数提供args,即你可以同时拥有它们;只要确保你有一个没有arg的人来满足上述用例。