类构造函数中的字段初始化:直接还是通过“setter”?

时间:2011-02-09 10:48:48

标签: java oop constructor initialization field

我在使用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

4 个答案:

答案 0 :(得分:4)

Getters Setters封装了这些东西。今天没有什么可以处理的,但明天你可能需要处理一些东西。所以最好使用Getters Setters。

对于默认值启动,您可以使用构造函数。\但如果在设置时使用Getters Setters进行了一些处理。

最佳做法是使用

  • 构造函数/ Initilizer阻止将成员字段初始化为其值。
  • 直接来自班级访问字段
  • 来自课堂外的
  • 使用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是不必要的,只会创建额外的方法调用来减慢程序的速度。我不确定它有多重要,因为这种方法调用通常在编译时内联。