为什么这仍然需要在 java 中投射?

why is this still need to cast in java?

错误

public class DefaultLiteProcessScopeFactory<S extends DefaultLiteProcessScope> implements LiteProcessScopeFactory<S> {
    @Override
    public S build() {
        return new DefaultLiteProcessScope();
    }
}

public class DefaultLiteProcessScopeFactory<S extends DefaultLiteProcessScope> implements LiteProcessScopeFactory<S> {
    @Override
    public S build() {
        return (S) new DefaultLiteProcessScope();
    }
}

DefaultLiteProcessScope 扩展了 DefaultLiteProcessScope,但直到需要强制转换?为什么?

S 扩展了 DefaultLiteProcessScope,因此您正在尝试 return 父 class 实例而不是子 class 实例。

原因是代码错误

public class MyOtherFactory<SubclassOfDefaultLiteProcessScope> {}

会中断,因为 DefaultLiteProcessScope 不是 SubclassOfDefaultLiteProcessScope。

您的代码会在以下实例中抛出 ClassCastException

class CustomLiteProcessScope extends DefaultLiteProcessScope { ... }

final DefaultLiteProcessScopeFactory<CustomLiteProcessScope> factory = new ...;

然后:

factory.build(); <-- Exception trying to cast DefaultLiteProcessScope to CustomLiteProcessScope

你在这里做的是错误的。您想要从 build 方法中 return DefaultLiteProcessScope 的某些子类型。但是,您可以像这样硬编码 return 类型:new DefaultLiteProcessScope()。现在想像这样一个稍微做作的例子。

static class SubType extends DefaultLiteProcessScope {
        
}

然后是客户端代码。

final LiteProcessScopeFactory<SubType> f = new DefaultLiteProcessScopeFactory<>();
final SubType result = f.build();

现在,由于您有 hard-coded return 类型,您的编译器无法保证代码的类型安全。我希望它是 return 子类型,但是你有 hard-coded 而不是 super-type。因此,它会要求您添加显式强制转换,这很公平,不是吗?事实上,此转换在运行时失败并抛出 java.lang.ClassCastException,因为超类型 DefaultLiteProcessScope 无法转换为子类型 SubType.

如何修复。

更好的方法是像这样将供应商作为参数传递给您的构建方法。

static class DefaultLiteProcessScopeFactory<S extends DefaultLiteProcessScope> implements LiteProcessScopeFactory<S> {
    @Override
    public S build(Supplier<S> s) {
        return s.get();
    }
}

static interface LiteProcessScopeFactory<S> {
    S build(Supplier<S> s);
}

这是新的客户端代码。

final LiteProcessScopeFactory<SubType> f = new DefaultLiteProcessScopeFactory<>();
final SubType result = f.build(SubType::new);