简体   繁体   English

通过工厂模式设置最终变量

[英]Setting final variables via Factory Pattern

I am using GWT and am constrained to having zero argument constructors.我正在使用 GWT 并且被限制为具有零参数构造函数。 This means that I am using a static factory method on each class in order to set member variables:这意味着我在每个 class 上使用 static 工厂方法来设置成员变量:

public class Point {
    private final float x;
    private final float y;

    public static Point build(float x, float y) {
        Point p = new Point();
        p.x = x;
        p.y = y;
        return p;
    }

    // getters for x and y
    // other methods...
}

Now the problem here is that x and y can not be final as I am setting them outside of the constructor, but ideally I want them to be immutable.现在这里的问题是 x 和 y 不能是最终的,因为我将它们设置在构造函数之外,但理想情况下我希望它们是不可变的。

What is the best approach?最好的方法是什么?

It's a good idea to have the language enforce as many properties of your program as possible, and making use of the final keyword is certainly good practice.让语言强制执行尽可能多的程序属性是一个好主意,并且使用final关键字当然是一个好习惯。 But this is a case where the final keyword is just too strict to make the serialization mechanism of GWT work, at least in it's current state.但在这种情况下, final关键字过于严格,无法使 GWT 的序列化机制起作用,至少在当前的 state 中是这样。 Therefore you sadly can't make use of this feature.因此,遗憾的是您无法使用此功能。

But I think it's worth to mention that, if you don't provide setters for x and y and keep them private , you class indeed is immutable .但我认为值得一提的是,如果您不提供 x 和 y 的设置器并将它们private ,那么您的 class 确实是不可变的 It's just not the language enforcing this, it's your code.这不是强制执行此操作的语言,而是您的代码。

The class only needs to have an empty constructor to support serialization. class 只需要一个空的构造函数就可以支持序列化。 You can also have other constructors as well so you don't need your factory method.您也可以拥有其他构造函数,因此您不需要工厂方法。 That said you can't have final variable because of the need for the zero argument constructors.也就是说,由于需要零参数构造函数,您不能拥有最终变量。

Hopefully this will be sorted out in a future release (See http://code.google.com/p/google-web-toolkit/issues/detail?id=1054 )希望这将在未来的版本中得到解决(参见http://code.google.com/p/google-web-toolkit/issues/detail?id=1054

Are you really constrained to a zero argument constructor?你真的受限于零参数构造函数吗? There might be a way telling GWT that you want to use a Constructor with Parameters.可能有一种方法告诉 GWT 您想使用带参数的构造函数。 Anyway the suggestion of Waldheinz is the same thing i would have suggested.无论如何,Waldheinz 的建议与我的建议相同。

But another thing to think about probably is, that GWT will use this default constrcutor to create an instance of this class at some point.但可能要考虑的另一件事是,GWT 将在某个时候使用此默认构造函数来创建此 class 的实例。 So if your class depends on those two instance fields to have a valid value that could lead to errors.因此,如果您的 class 依赖于这两个实例字段以具有可能导致错误的有效值。

If your zero-arg constructor constraint is only because of GWT-RPC, then you can overcome this using a custom field serializer: it has to be a class in the same package, named the same as the class to be serialized but with a _CustomFieldSerializer suffix and extending CustomFieldSerializer .如果您的零参数构造函数约束仅仅是因为 GWT-RPC,那么您可以使用自定义字段序列化程序来克服这个问题:它必须是同一个 package 中的 class,名称与 ZA2F2ED4F8EBC2CBB4C21A29DC 相同,但名称与_CustomFieldSerializer后缀和扩展CustomFieldSerializer
You can follow the java.lang.Boolean custom field serializer as an example.您可以按照java.lang.Boolean自定义字段序列化程序为例。 In your case, this should work:在您的情况下,这应该有效:

public final class Point_CustomFieldSerializer extends CustomFieldSerializer<Point> {
  @Override
  public boolean hasCustomInstantiateInstance() { return true; }

  @Override
  public Point instantiateInstance(SerializationStreamReader streamReader) throws SerializationException {
     return new Point(streamReader.readInt(), streamReader.readInt());
  }

  @Override
  public void deserializeInstance(SerializationStreamReader streamReader, Point instance) throws SerializationException {
    // everything is done in instantiateInstance
  }

  @Override
  public void serializeInstance(SerializationStreamWriter streamWriter, Point instance) throws SerializationException {
    streamWriter.writeInt(instance.getX());
    streamWriter.writeInt(instance.getY());
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM