使用许多可选数据成员初始化类的Java最佳实践是什么?

时间:2015-01-07 11:26:44

标签: java initialization

我正在将项目从C#迁移到Java。

我有很多类,它们有很多属性,用户可以设置它们的任何子集。

因此,为了初始化类,我提供了一个空构造函数,用户可以使用C#初始化列表初始化任何属性,如下所示:

var a = new MyClass() { Prop1 = "something", Prop2 = 8, Prop15 = new Point(2,3) };

Java中这种情况的最佳做法是什么?

我看过以下语法:

    MyClass a = new MyClass(){
            {
                setProp1("Something");
                setProp2(8);
                setProp15(new Point(2,3));
            }
    };

但是,我知道这不仅仅是一个语法糖,它实际上创建了一个匿名类,并将所有方法放在新类的初始化块中。

所以我不确定这是初始化这样一个类的推荐方法。

这种情况的建议是什么?

4 个答案:

答案 0 :(得分:2)

您必须为您的班级创建POJO,然后使用它的setter方法初始化它。

class MyClass{

  Prop1 = null;
  Prop2 = null;

// getter and setter method

}

答案 1 :(得分:2)

拥有匿名子类的对象通常并不坏。当你使用if (object.getClass() == MyClass.class)这样的结构时,它只会成为一个问题,但是当你编写适当的面向对象的代码时,这些并不是必需的。更好地使用if (object instanceof MyClass),对于MyClass的子类也是如此,或者更好地将任何特定于类的代码放入类本身。

初始化具有许多属性的对象的另一种方法是使用Builder模式。

创建一个嵌套在MyClass内的公共类,其目的是创建一个MyClass实例。因为它嵌套在MyClass内,所以它可以访问它正在初始化的实例的所有私有字段。使用这样的构建器可能如下所示:

MyClass a = new MyClass.Builder().setProp1("Something")
                                 .setProp2(8)
                                 .setProp15(new Point(2,3))
                                 .build();

此示例使用带有fluent interface的构建器:所有setter返回this,允许您在方法调用之间使用简单的.进行链接。

答案 2 :(得分:2)

我喜欢使用定义类。

public class VehicleDef
{
     int wheels;
     Color color;
     Brand brand;
     Type type;
     int cylinderVolume;
     ....
}

现在,您可以创建一个构造函数,将此VehicleDef类作为参数:

public class Vehicle
{
    // all props here:

    public Vehicle (VehicleDef def)
    {
        // set properties and do stuff
    }
}

现在,您可以像这样使用它:

VehicleDef def;
def.wheels = 4;
def.color = Color.RED;
def.brand = Brands.HONDA;
def.type = VehicleTypes.CAR;
def.cylinderVolume = 400;

Vehicle vehicle = new Vehicle(def);

答案 3 :(得分:0)

没有双括号初始化:

MyClass a = new MyClass();
a.setProp1("Something");
a.setProp2(8);
a.setProp15(new Point(2,3));

如果(可变)属性的数量很大,这是可行的方法。

当某些属性是不可变的(最终)时,添加特定的构造函数是必要的。 可以添加任意数量的附加构造函数以在构造时传递属性(如果可能,还添加一个没有args的默认构造函数):

public class MyClass {

    // default constructor
    public MyClass() {
    }

    // convenience constructor
    public MyClass(String s, int i, Point p) {
        setProp1(s);
        setProp2(i);
        setProp15(p);
    }
}