gpt4 book ai didi

java - 使用泛型作为返回类型

转载 作者:行者123 更新时间:2023-11-30 08:51:15 24 4
gpt4 key购买 nike

我有这样的结构:

abstract class MyDomain{...}
abstract class FooDomain extends MyDomain{...}
abstract class BarDomain extends MyDomain{...}
class FirstConcreteBarDomain extends BarDomain{...}
class SecondConcreteBarDomain extends BarDomain{...}

我需要一个创建 MyDomain 对象的工厂。我的第一次尝试是这样的:

public interface ISpecializedObjectsFactory {
public <T extends MyDomain> T create(Class<?> clazz);
}

实现为:

public class FirstSpecializedObjectsFactory implements ISpecializedObjectsFactory {

@Override
public <T extends MyDomain> T create(Class<?> clazz) {
if(clazz.equals(BarDomain.class))
return new FirstBarDomain();
throw new InvalidParameterException();
}

SecondBarDomain 也是如此。

第一个问题:为什么这会生成一个错误,表明它无法将 FirstBarDomain 转换为 T

在这个错误之后我引入了一个转换:return (T) new FirstBarDomain();

问题是转换是不安全的,我想对结果有信心,所以我引入了另一个约束(假设每个 MyDomain 对象总是有 2 个派生级别):

public <T extends AnagrafeDomain, S extends T> S create(Class<T> clazz)

第二个问题:假设这个工厂是创建 MyDomain 对象的唯一入口点,并且对工厂的调用从不使用具体类(但是总是喜欢:BarDomain subj = SpecializedObjectsFactory.getFactory().create(BarDomain.class);),问题是:这个新版本安全吗?

最佳答案

转换不安全的原因是因为这一行:

public <T extends MyDomain> T create(Class<?> clazz) {

这从调用站点推断返回类型;换句话说,考虑以下类:

public abstract class MyFakeDomain extends MyDomain { }

下面的代码会编译,但在运行时会失败:

ISpecializedObjectsFactory factory = new FirstSpecializedObjectsFactory();
MyFakeDomain broken = factory.create(BarDomain.class);

这将抛出 ClassCastException因为类型推断;推断的类型将是 MyFakeDomain,导致尝试将 FirstBarDomain 转换为 MyFakeDomain,这是非法转换 - 因此出现不安全警告。

类型推断也是强制转换必须存在的原因;而 FirstBarDomain 肯定是 MyDomain 的子类,我们不知道它是否是 T 类型,因为 T可以是任何 MyDomain 子类,不一定是FirstBarDomain

但是,如果调用者小心,您的代码将正常工作 - 您是否认为这可以接受取决于您。

这为我们提供了第二个问题的答案:使用 BarDomain 作为要推断的类型并不总是安全的,因为它可能是 MyDomain 的另一个子类。唯一在这里始终安全的类型是 MyDomain - 但是,如果您计划只使用 MyDomain 作为类型,您不妨删除通用类型绑定(bind)和只需将返回类型设为 MyDomain

关于java - 使用泛型作为返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30639911/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com