我有以下带有builder()方法的Manager类:
public class Manager extends Employee {
public static Manager.Builder builder() {
return new ManagerBuilder();
}
public abstract static class Builder<T extends Employee, B extends Builder<T,B>> extends Employee.Builder<T,B>{
}
public static class ManagerBuilder extends Builder<Manager,ManagerBuilder> {
@Override
protected ManagerBuilder self() {
return this;
}
@Override
public Manager build() {
return new Manager(this);
}
}
}
不幸地尝试使用Manager.builder().age(25).build();
构建一个对象,而不是我需要的人,而不是经理。
如何更改Manager.builder()返回类型以返回Manager,同时不与Employee.builder()方法签名冲突。
代码Employee.builder().age(25).build();
返回Employee,没问题。
员工类看起来像这样:
public class Employee extends Person {
public static Employee.Builder<Employee, EmployeeBuilder> builder() {
return new EmployeeBuilder();
}
public abstract static class Builder<T extends Person, B extends Builder<T,B>> extends Person.Builder<T,B>{
}
public static class EmployeeBuilder extends Builder<Employee, EmployeeBuilder> {
@Override
protected EmployeeBuilder self() {
return this;
}
@Override
public Employee build() {
return new Employee(this);
}
}
}
public class Person implements PersonInterface {
private Optional<Integer> age;
protected Person(Builder<?,?> builder) {
this.age = builder.age;
}
public abstract static class Builder<T extends Person, B extends Builder<T,B>> {
private Optional<Integer> age;
protected Builder() {
}
public B age(Integer age) {
if (Objects.isNull(age) || age == 0) throw new IllegalArgumentException("Age ist empty");
this.age = Optional.of(age);
return self();
}
protected abstract B self();
public abstract T build();
}
public static class PersonBuilder extends Builder<Person, PersonBuilder>{
@Override
protected PersonBuilder self() {
return this;
}
@Override
public Person build() {
return new Person(this);
}
}
}
答案 0 :(得分:2)
核心问题是你的奇怪的继承结构,它重载了类名Builder
。我无法解决问题,但在某些时候,ManagerBuilder
的特定类型信息会丢失。这可以简化很多:
public class Employee extends Person {
public static EmployeeBuilder builder() {
return new EmployeeBuilder();
}
public static class EmployeeBuilder extends Person.Builder<Employee, EmployeeBuilder> {
@Override
protected EmployeeBuilder self() {
return this;
}
@Override
public Employee build() {
return new Employee(this);
}
}
}
public class Manager extends Employee {
public static ManagerBuilder builder() {
return new ManagerBuilder();
}
public static class ManagerBuilder extends Person.Builder<Manager, ManagerBuilder> {
@Override
protected ManagerBuilder self() {
return this;
}
@Override
public Manager build() {
return new Manager(this);
}
}
}
这可以解决你的一些问题。
现在你还有一个问题。静态方法builder
重载了不兼容的返回类型。您可以在Why does Java enforce return type compatibility for overridden static methods?找到相关信息
如果您以不同的方式命名这些方法,它应该可以工作。
答案 1 :(得分:1)
您的代码运行良好,Manager.builder().age(25).build()
实际返回Manager
。这只是编译时的问题。
以下Junit测试应该成功(它在我的测试中确实):
@Test
public void testEss3() throws Exception {
Person emp = Manager.builder().age(25).build();
assertTrue(emp instanceof Manager);
}
实际上,当您声明没有变量来托管构建器时,并且由于方法age
未在Manager.Builder
中定义,也未在其直接子类Employee.Builder
中定义,因此编译器假定它将返回声明它的类的对象,即Person.Builder
。它不是假的,因为它实际上是一个祖先类。但是从那时起,编译器不知道build()
返回的确切类,只知道它将是Person
。
但是下面的代码是编译器的接受者:
Manager.Builder<Manager,?> builder = Manager.builder();
Manager emp = builder.age(25).build();