【发布时间】:2021-01-04 04:17:11
【问题描述】:
我有一些对象可以预先生成一些配置,以便它们以后可以更快地处理计算(可能是几次)。我正在尝试对其进行通用化以避免将配置作为Object 传递并每次都进行转换。
interface IComputable<T> {
T configure(); // Generate configuration object
int compute(T conf); // Run the computation based on the pre-generated configuration
float precision(T conf); // Make the compute() computation finer-grained
...
}
class ComputableInfo {
IComputable<?> computable;
Object config; // Real type is <?>
int result;
ComputableInfo(String id) {
computable = ComputableFactory.createFrom(id);
config = computable.configure();
result = computable.compute(config); // <<<--- The method compute(capture#3-of ?) in the type TestInterface.IComputable<capture#3-of ?> is not applicable for the arguments (Object)
}
}
我收到编译错误:
TestInterface.IComputable
类型中的方法 compute(capture#3-of ?) 不适用于参数 (Object)
当然,我可以将int compute(T conf) 替换为int compute(Object conf),但我必须将其显式转换为适当的T。这不是什么大问题,但它使代码不那么明显。
我也可以将ComputableInfo 设为通用
interface ComputableInfo<T> {
IComputable<T> computable;
T config;
...
但这会在其他一些地方产生编译问题(主要是“原始类型”警告),我想避免比以前的解决方法更多的地方(使用Object而不是T)。
有没有办法做到这一点?我什至愿意在编译器设置中将此类问题从错误变为警告,或者可能有一个额外的私有方法可以在单个对象中返回 config 和 result?
编辑:如果我将ComputableInfo 设为通用,则添加“进一步的编译问题”:我在接口中有另一个方法(参见已编辑),它通过ComputableInfo 调用:
ComputableInfo<?> info = getInfo(id);
info.computable.precision(info.config); // <<<--- (same kind of error)
问题是ComputableInfo 无法知道Computable<T> 的T 类型(或者我不知道),因为它来自一个从配置文件构建它的工厂。
【问题讨论】:
-
使
ComputableInfo类型泛型是 正确的解决方案。修复其他警告。 -
你得到编译错误的原因是因为
IComputable<?>是一个IComputable,它包含一些未知类型,你不能将任意Object传递给它,因为编译器没有办法检查该对象的类型是否正确。与您无法添加到List<?>的原因相同,在 SO 上已多次询问和回答。您可以将您的IComputable<?>转换为IComputable<Object>,但这是一个丑陋且类型不安全的 hack。 -
@chrylis-cautiouslyoptimistic- 我已编辑以进一步解释:我得到的“原始类型”警告可以通过使用
<?>对其进行参数化来删除,这会删除类型并创建错误而不是警告。不过,我仍在调查这条路线…… -
@Jesper 确实我理解编译器为什么抱怨它。我已经详细介绍了 Factoy 创建 Computables、擦除参数化...
-
IComputable<? super Object> computable;怎么样?
标签: java generics java-8 type-conversion wildcard