为了账号安全,请及时绑定邮箱和手机立即绑定

如何在泛型类中正确键入 no-arg 和 withVar 构造函数?

如何在泛型类中正确键入 no-arg 和 withVar 构造函数?

摇曳的蔷薇 2023-06-04 19:47:47
我正在研究一个(Java 8+)类,我想使用一种“构建器”模式构建它,在该模式中,您将无参数构造函数链接到一个或多个返回相同对象的设置器。基本上这是我的课:public class MyClass {  private int foo;  private String bar;  public MyClass() {    System.out.println("initializing instance of MyClass");  }  public MyClass withFoo(int foo) {    this.foo=foo;    return this;  }  public MyClass withBar(String bar) {    this.bar = bar;    return this;  }}您初始化它的典型方法是MyClass anInstance = new Myclass().withFoo(42).withBar("helloworld");这是一个很好的模式,但我以前从未将它用于泛型类。现在我想泛化我的班级。我对类签名和构造函数、withFoo 和 withBar 方法进行了更改:public class MyClass<T> {  private int foo;  private String bar;  public MyClass() {    System.out.println("initializing instance of MyClass");  }  public MyClass<T> withFoo(int foo) {    this.foo=foo;    return this;  }  public MyClass<T> withBar(String bar) {    this.bar = bar;    return this;  }}请注意,foo它们bar自己不会改变类型。任何类型<T>都不会通过方法传入withVar()。我有一些线索表明这不是最好的方法。标准的无参数构造函数似乎工作正常:工作正常: MyClass<Float> myInstance = new MyClass<>();但是,如果我添加一个withVar函数,我会在编译时遇到错误(java:不兼容的类型:MyClass 无法转换为 MyClass)。不会编译: MyClass<Float> myInstance = new MyClass<>().withFoo(42);我可以通过两次指定类型来使其工作,如下所示:工作正常: MyClass<Float> myInstance = new MyClass<Float>().withFoo(42);有没有更好的方法来编写代码,以便将泛型类型正确地传递到赋值运算符的右侧?
查看完整描述

1 回答

?
凤凰求蛊

TA贡献1825条经验 获得超4个赞

我能做到这一点的唯一两种方法是添加一个指定类型的构造函数参数:


MyClass<Float> instance = new MyClass<>(0.f).withFoo(42).withBar("helloworld");

或者通过添加“终端投射”方法:


public class MyClass<T> {

  // ...


  public MyClass() { ... }


  public <U> MyClass<U> cast() {

    MyClass<U> copy = new MyClass<>();

    return copy.withFoo(foo).withBar(bar);

  }


  public MyClass<T> withFoo(int foo) { ... }

  public MyClass<T> withBar(String bar) { ... }

}

然后你可以像这样调用它:


MyClass<Float> instance = new MyClass<>().withFoo(42).withBar("helloworld").cast();

第三种方法是提供一个MyClass<Float>专门用于创建实例的工厂方法:


static MyClass<Float> newFloatInstance() { return new MyClass<>(); }

然后你可以像这样调用它:


MyClass<Float> instance = newFloatInstance().withFoo(42).withBar("helloworld");

但我猜你可能真的不想为每种可能的类型都使用工厂方法。


但是请注意,如果您能够在不向 cast 方法(或构造函数)提供将其实例与其MyClass类型参数相关联的情况下执行此操作,那么您实际上不需要类上的类型变量。


您可以将类型变量推送到需要该类型变量的方法上:


public class MyClass {

  // ...


  public <T> T doSomethingToSpecificType(List<T> list, T arg) {

    // do something type-specific.

  }

}


查看完整回答
反对 回复 2023-06-04
  • 1 回答
  • 0 关注
  • 134 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信