java - 如何确保仅协变地使用类型参数?

标签 java unit-testing generics static-analysis covariance

假设我有一个通用接口(interface) Source<T>这是T的纯生产商对象。作为一个纯粹的生产者是接口(interface)契约的一部分。所以it is a reasonable expectation无论你能用 Source<Foo> 做什么, 如果你有 Source<? extends Foo> 也应该可以做到.

现在我需要在 Source 的正文中强制执行此限制, 这样就不会有人不小心使用了 T以一种与该契约(Contract)相矛盾的方式。

来自 JDK 的示例

正如@Miserable.Variable 指出的那样,ArrayList<Integer>ArrayList<? extends Integer> 等价。那是因为ArrayList作为通用类型不是协变的。或者换句话说,ArrayList<T>不是T的纯粹生产者;具体来说,ArrayList方法 add(T) 消耗 T .

但是有些泛型是纯粹的生产者,比如 IteratorIterable . Iterator<Integer> 可以做什么你也可以用 Iterator<? extends Integer> .没有像 ArrayList.add(T) 这样的方法在Iterator<T> .

我只想确保我的界面 Source<T>就像Iterator<T>而不是喜欢 ArrayList<T> .如果以后有人加一个T -consuming 方法(如 add(T) )到我的界面,我希望他们得到一个明确的错误。

一个更复杂的例子

简单地禁止 T 类型的参数出现在界面中并不是一个完整的解决方案。还应注意 T可能用作其他泛型类型的参数。例如,Source<T> 中不应允许使用以下方法:

public void copyTo(List<T> destination);

因为偷偷摸摸的子类可能会尝试从列表中读取,所以它被认为是 T -消费者;您不能在 Source<? extends Foo> 上调用此方法.另一方面,应该允许这个:

public void copyTo(List<? super T> destination);

(还有一条规则说 Source<T> 中的方法不能返回 List<T>,但可以返回 List<? extends T>。)

现在,实际的接口(interface)可以任意复杂,有很多方法,规则本身也很复杂。很容易出错。所以我想自动执行此检查。

是否有单元测试技巧、静态分析器、编译器/IDE 插件、注释处理器(例如在 @Covariant 上使用 T 注释)或任何其他技术或工具可以确保这一点?

最佳答案

这不是答案,但太长了,不适合放在评论中。

So it is a reasonable expectation that whatever you can do with a Source<Foo>, should be also possible to do if you have a Source<? extends Foo>

不,这不是一个合理的期望。您链接到整个 pdf,它转到 top level page所以不清楚你是如何确定这是合理的,但总的来说你不能任意替换一个 Foo<T>Foo<? extends T> .敌人的例子,如果你有一个 ArrayList<Integer> a你可以调用a.Add(Interger.valueOf(5))但是如果 a 你不能这样做是ArrayList<? extends Integer> a .

也不清楚什么是Consumer<T>sendTo .后者是Source<T>中的方法吗? >?

如果没有这些澄清,恐怕他的问题是模棱两可的。

关于java - 如何确保仅协变地使用类型参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14014701/

相关文章:

java - 如何将 CSV 文件加载到 Apache Arrow vectors 并将箭头文件保存到磁盘

unit-testing - 在测试类中,在断言中使用主题类的常量是个好主意吗?

unit-testing - 简单 grails Controller 单元测试中的空指针

Java 泛型和扩展的比较

java - JsValue 中的 Scala 模式匹配类型

java - GWT 代码 - 如何强制工具提示带有换行符?

java - 如何在不使用循环的情况下在 java 的 json 中解析数组中的每个对象?

java - 使用静态列表保留Java中的所有线程

unit-testing - GGTS无法运行grails单元测试:java.lang.NoClassDefFoundError:org/w3c/dom/ElementTraversal

Java - 使用通配符列表创建数组列表