我在使用C ++和C#一段时间后正在开发Java项目,我对构造函数中的字段初始化的最佳实践存在疑问。基本上,假设我有一个简单的Point类。在C ++中,构造函数中的字段初始化如下所示:
class Point {
public:
// Default constructor
Point(double x, double y) : x(x), y(Y) { }
protected:
// Coordinates
double x, y;
};
在C#...
class Point {
// Coordinates, with automatic properties
public double X { get; protected set; }
public double Y { get; protected set; }
// Default constructor
Point(double x, double y) {
X = x;
Y = y;
}
}
在Java中......最佳实践建议为必须从外部访问的字段定义getter / setter。但是建议在课堂上使用它们吗?令人怀疑的是,Eclipse似乎很乐意将类代码中的每个this.field = field
转换为具有getter / setter的字段的setField(field)
,即使我在类代码内部进行读/写操作(因此我不需要使用类接口)。
这基本上为每次访问添加了一个函数调用。现在,除了设置字段涉及一些其他操作(即验证,处理等)的情况之外,这有什么意义吗?常识会建议使用getter / setter类似于使用C#属性,但在这里我特别质疑C#的自动属性,它只涉及基本访问,没有任何处理。所以问题是:在类代码中没有额外的处理来调用getter / setter有什么好处吗?
谢谢你 Tunnuz
答案 0 :(得分:4)
Getters Setters封装了这些东西。今天没有什么可以处理的,但明天你可能需要处理一些东西。所以最好使用Getters Setters。
对于默认值启动,您可以使用构造函数。\但如果在设置时使用Getters Setters进行了一些处理。
最佳做法是使用
另见
答案 1 :(得分:2)
我也更喜欢直接访问。但是,对于非平凡的get / setter,如果内部也需要非平凡的语义,您可能希望使用它们。
如果你事先并不知道get / setters是非trival,那么你也可能事先不知道内部是否也应该执行额外的工作,所以过早的封装不是有用,因为它可能会出现。
我的Eclipse(Helios)安装没有进行此转换,因此我假设您可以将其关闭。
答案 2 :(得分:1)
如果要对要设置的值进行一些验证,格式化或处理,可以推荐使用setter。
假设你需要你的类Foo总是需要一个非空的条形值,当不使用setter时,你需要在每次设置值时重写验证代码:
public class Foo {
private String bar;
public Foo(String aValue) {
if(aValue==null || aValue.equals("")) {
throw new IllegalArgumentException("Duh");
}
bar=aValue;
}
public void setBar(String aValue) {
if(aValue==null || aValue.equals("")) {
throw new IllegalArgumentException("Duh");
}
bar=aValue;
}
}
使用setter,您可以重用代码,并允许在一个点上实现更多逻辑:
public class Foo {
private String bar;
public Foo(String aValue) {
setBar(aValue);
}
public void setBar(String aValue) {
if(aValue==null || aValue.equals("")) {
throw new IllegalArgumentException("Empty values not allowed");
}
if(aValue.length()>24) {
throw new IllegalArgumentException("Too long");
}
bar=aValue;
}
}
答案 3 :(得分:0)
正如我所教,在构造函数中使用getter和setter是不必要的,只会创建额外的方法调用来减慢程序的速度。我不确定它有多重要,因为这种方法调用通常在编译时内联。