【发布时间】:2021-01-15 22:35:03
【问题描述】:
我希望实现一个具有以下签名的方法:
<T> void function(Class<T> clazz, Consumer<T> consumer)
这个函数接受Object obj(在别处提供),使用clazz.cast(obj) 将其转换为T,然后用它调用consumer。 (基本上就是consumer的守卫。)
这工作或多或少都很好,我可以写
Consumer<String> c = ...;
function(String.class, c);
很遗憾,以下代码不起作用:
Consumer<List<String>> c = ...;
function(List.class, c);
这是因为 List.class 的类型为 Class<List>,而不是类 Class<List<String>>。
我可以将c 的类型更改为Consumer<List>,但这与我在其他地方的代码不兼容(而且原始类型也不好)。
是否有某种方法可以 (a) 以类型检查的方式调用 function,或 (b) 以使该模式起作用的方式更改 function 的类型签名?
注意事项:
-
我希望尽可能多地保留编译和运行时类型的安全性。因此,
function(Class<?> clazz, Consumer<T> consumer)是不可接受的,因为用户很容易提供错误的clazz。并且调用为function((Class<List<String>>)List.class, c)也是不可接受的,因为我可能会不小心将其转换为function((Class<Integer>)List.class, c)和 这个错误的演员阵容甚至不会在运行时被发现。如果有一个函数允许将Class<C<T>>转换为Class<C<U>>但不能转换为Class<D>,那会很酷,但如果没有高阶类型,我看不到这一点。 -
我知道类型转换将无法在运行时检查我们有
List<String>而不是List<Integer>。没关系。 (嗯,不是,但我认为这是最好的 我们可以期待 JVM 语言。) -
尽管如此,我更喜欢使
function的调用变得简单(可能使function更复杂)的解决方案,因为function在我的库中定义并由该库的用户使用。 -
出于好奇,我遇到此问题的实际代码是here,
Instance是function。
【问题讨论】:
标签: java generics types casting