- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有这样的结构:
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/
我是一名优秀的程序员,十分优秀!