Java 如何泛化返回其调用对象的方法的返回类型

Java 如何泛化返回其调用对象的方法的返回类型,java,generics,Java,Generics,如果这个问题已经被问过,我就找不到了。 下面是一个我正在尝试做的简单示例 public static class SuperClass { private String name; public <? extends SuperClass> setName(String name) this.name = name; return this; } } public static class SubClass extends

如果这个问题已经被问过,我就找不到了。 下面是一个我正在尝试做的简单示例

public static class SuperClass {
    private String name;

    public <? extends SuperClass> setName(String name)
        this.name = name;
        return this;
    }
}

public static class SubClass extends SuperClass {
    private int id;

    public void setId(int id) {
        this.id = id;
    }
}

//Usage
SubClass subclass = new SubClass();
subClass.setName("Some Name").setId(0);
所以我需要的是,setName返回它实际上从哪个类调用的,与它在中定义的类相反。在这种情况下,它将返回子类而不是超类的实例,但如果例如子类被子类2扩展,它将返回子类2的实例

我所问的是否可以通过泛型实现?

您可以向超类声明中添加一个类型,并在setName方法的返回类型中使用它。 它将强制所有继承的子类返回在其对超类的扩展声明中声明的类型。 但要实现它,您应该在setName中将其强制转换为T

另一种解决问题的方法:

在重写的方法中使用协变返回类型将允许您在返回的类型中指定子类。你可以用它代替泛型。 需要注意的一点是:您必须小心地通过重写每个子类中的方法来显式定义返回类型。 如果没有泛型,除了单元测试之外,没有什么能强迫您这么做

public class SuperClass {
    private String name;

    public SuperClass setName(String name) {
      this.name = name;
      return this;
    }
}

public class SubClass extends SuperClass {

    @Override
    public SubClass setName(String name) {
       super.setName(name);
       return this;
    }

    public void setId(int i) {
       ...
    }
}

公共静态超类{不编译public不可能按您的要求编译。您应该查看生成器designpattern不可能。此类不能与t相同这是我尝试过的事情之一。我希望不需要在类中设置类型。我的ide还抱怨未选中的强制转换,这使对我来说很有意义,因为T必须扩展超类。我想我会接受@rollback的建议,使用一个生成器。它必须是一个泛型生成器,因为会有很多不同的类扩展基类,但它应该是可行的。编辑:再想想,没有泛型生成器根本不起作用……显然……使用泛型,将每个子类的特定子类设置为返回类型需要在超类扩展的声明中声明该类型。您没有选择。不安全的向下转换可能也很烦人,但这里仍然是泛型在Java中的工作方式。泛型构建器根本不起作用。确实如此。但是,在ided方法将允许您在返回的类型中指定子类。您可以使用它而不是泛型。需要注意的一点是:您必须小心地在重写的方法中显式定义返回类型。没有泛型,任何事情都不会强迫您这样做。
public class SubClass extends SuperClass<SubClass> {
     ...
    public void setId(int i) {
       ...
    }
   ...
}
SubClass subclass = new SubClass();
subclass.setName("Some Name").setId(0);
public class SuperClass {
    private String name;

    public SuperClass setName(String name) {
      this.name = name;
      return this;
    }
}

public class SubClass extends SuperClass {

    @Override
    public SubClass setName(String name) {
       super.setName(name);
       return this;
    }

    public void setId(int i) {
       ...
    }
}