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

发布于 2024-11-24 18:32:54 字数 432 浏览 2 评论 0原文

我正在使用 GWT,并且只能使用零参数构造函数。 这意味着我在每个类上使用静态工厂方法来设置成员变量:

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...
}

现在的问题是 x 和 y 不能是最终的,因为我在构造函数之外设置它们,但理想情况下我希望它们是不可变的。

最好的方法是什么?

I am using GWT and am constrained to having zero argument constructors.
This means that I am using a static factory method on each class in order to set member variables:

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.

What is the best approach?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深海里的那抹蓝 2024-12-01 18:32:54

让语言强制执行尽可能多的程序属性是一个好主意,并且使用 final 关键字无疑是一个很好的做法。但在这种情况下,final 关键字过于严格,无法使 GWT 的序列化机制发挥作用,至少在当前状态下是如此。因此,遗憾的是您无法使用此功能。

但我认为值得一提的是,如果您不为 x 和 y 提供设置器并保持它们私有,那么您的类确实是不可变的。这不是强制执行此操作的语言,而是您的代码。

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. 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. 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. It's just not the language enforcing this, it's your code.

天涯离梦残月幽梦 2024-12-01 18:32:54

该类只需要有一个空的构造函数即可支持序列化。您还可以拥有其他构造函数,因此您不需要工厂方法。也就是说,由于需要零参数构造函数,因此您不能拥有最终变量。

希望这个问题能够在未来的版本中得到解决(请参阅 http ://code.google.com/p/google-web-toolkit/issues/detail?id=1054

The class only needs to have an empty constructor to support serialization. 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)

梦魇绽荼蘼 2024-12-01 18:32:54

您真的受限于零参数构造函数吗?可能有一种方法告诉 GWT 您想要使用带有参数的构造函数。不管怎样,瓦尔德海因茨的建议和我的建议是一样的。

但可能需要考虑的另一件事是,GWT 将在某个时候使用此默认构造函数来创建此类的实例。因此,如果您的类依赖这两个实例字段来获取有效值,则可能会导致错误。

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. Anyway the suggestion of Waldheinz is the same thing i would have suggested.

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. So if your class depends on those two instance fields to have a valid value that could lead to errors.

怪我闹别瞎闹 2024-12-01 18:32:54

如果您的零参数构造函数约束只是因为GWT-RPC,那么您可以使用自定义字段序列化器来克服这个问题:它必须是同一包中的类,命名与类相同要序列化,但带有 _CustomFieldSerializer 后缀并扩展 CustomFieldSerializer
您可以关注java.lang.Boolean 自定义字段序列化器 为例。在你的情况下,这应该有效:

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());
  }
}

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.
You can follow the java.lang.Boolean custom field serializer as an example. 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());
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文