我在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;
}
答案 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)
如果x
和y
是可变的并且具有非平凡的setter,那么使用setter初始化它们,即使在构造函数中也可以帮助避免重复代码。在这种情况下,您可能希望将setter标记为final
,以防止派生类重写这些方法并导致构造函数出现意外行为。
如果setter是微不足道的(没有其他代码的简单赋值)那么在构造函数中使用setter的理由就不多了。
如果变量是不可变的,那么最好不要使用setter并直接在构造函数中初始化它们。
答案 6 :(得分:-1)
此资源可能有所帮助:
http://en.wikipedia.org/wiki/JavaBean
我个人发现,使用无参数构造函数可以简化依赖注入。例如使用Spring IoC,虽然你当然可以指定构造函数args,但它不需要更简单。
此外,我发现编写单元测试更简单,原因相同,即您可以实例化所需的对象,为测试目的注入所需的属性,然后进行测试。因此,使用带有args的构造函数可能需要您使用对测试不特别感兴趣的对象进行设置。
也就是说,提供一个无参数构造函数并不是为了方便的构造函数提供args,即你可以同时拥有它们;只要确保你有一个没有arg的人来满足上述用例。