Sai*_*ali 7 java generics unit-testing static-analysis covariance
假设我有一个通用接口Source<T>,它是一个纯粹的T对象生成器.作为纯粹的生产者是界面合同的一部分.因此,Source<Foo>如果你有一个,那么无论你能做什么,都应该做也是合理的期望Source<? extends Foo>.
现在我需要强制执行这个限制Source,以便有人不会T以违反合同的方式意外使用.
JDK的一个例子
正如@ Miserable.Variable指出,ArrayList<Integer>和ArrayList<? extends Integer>是不等价的.那是因为ArrayList作为泛型类型不是协变的.换句话说,ArrayList<T>不是纯粹的生产者T; 具体地说,该ArrayList方法add(T) 消耗 a T.
但是有些泛型类型是纯生产者,比如Iterator或Iterable.无论你做什么,Iterator<Integer>你也可以做一个Iterator<? extends Integer>.有没有像法ArrayList.add(T)在Iterator<T>.
我只是想确保我的界面Source<T>是一样Iterator<T>,而不是象ArrayList<T>.如果将来某人在我的界面中添加了一个T消耗方法(比如add(T)),我希望他们得到一个明确的错误.
一个更复杂的例子
简单地禁止T出现在界面中的类型参数不是一个完整的解决方案.还应注意,T可以将其用作其他泛型类型的参数.例如,不应允许以下方法Source<T>:
public void copyTo(List<T> destination);
Run Code Online (Sandbox Code Playgroud)
因为偷偷摸摸的子类可能会尝试从列表中读取,它被认为是一个T消费者; 你不能在a上调用这个方法Source<? extends Foo>.另一方面,应该允许这个:
public void copyTo(List<? super T> destination);
Run Code Online (Sandbox Code Playgroud)
(还有另一个规则,说方法Source<T>不能返回List<T>,但可以返回List<? extends T>.)
现在,实际的界面可能是任意复杂的,有很多方法,规则本身也很复杂.犯错很容易.所以我想自动完成这项检查.
是否有单元测试技巧,静态分析器,编译器/ IDE插件,注释处理器(例如带有@Covariant注释T),或任何其他可以确保这一点的技术或工具?
这不是答案,但太长,不适合评论。
因此,合理的期望是,无论您能用 a 做什么
Source<Foo>,如果您有 a ,也应该可以做到Source<? extends Foo>
不,这不是一个合理的期望。您链接到整个 pdf,它会转到顶级页面,因此不清楚您如何确定这是合理的,但一般来说您不能随意将 a 替换Foo<T>为Foo<? extends T>。例如,如果你有一个,ArrayList<Integer> a你可以打电话,但如果是 a.Add(Interger.valueOf(5)),你就不能这样做。aArrayList<? extends Integer> a
也不清楚什么是Consumer<T>和sendTo。Source<T>后者是>中的方法吗?
如果没有这些澄清,我担心他的问题是模棱两可的。