我有一些对象可以预先生成一些配置,以便它们以后可以更快地处理计算(可能是几次)。我正在尝试对其进行通用化以避免将配置作为 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)
}
}
我收到编译错误:The method compute(capture#3-of ?) in the type TestInterface.IComputable<capture#3-of ?> is not applicable for the arguments (Object)
当然,我可以替换
int compute(T conf)
通过 int compute(Object conf)
但我必须明确地将其转换为适当的 T
.这不是什么大问题,但它使代码不那么明显。我也可以制作
ComputableInfo
通用的interface ComputableInfo<T> {
IComputable<T> computable;
T config;
...
但这会在其他一些地方产生编译问题(主要是“原始类型”警告),我想避免比以前的解决方法更多的问题(使用 Object
而不是 T
)。有没有办法做到这一点?我什至愿意在编译器设置中将此类问题从错误变为警告,或者可能有一个额外的私有(private)方法可以同时返回
config
和 result
在单个对象中?编辑:如果我制作
ComputableInfo
,则添加“进一步的编译问题”通用:我在接口(interface)中有另一个方法(见已编辑),通过 ComputableInfo
调用:ComputableInfo<?> info = getInfo(id);
info.computable.precision(info.config); // <<<--- (same kind of error)
问题是 ComputableInfo
没办法知道T
Computable<T>
的类型(或者我不知道),因为它来自一个从配置文件构建它的工厂。
最佳答案
从通配符类型中获取对象并将其传递回同一对象,这是泛型类型系统的一个已知限制。例如,当你有
List<?> list = …
您可能希望将元素从一个索引复制到另一个索引,例如Object o = list.get(0);
list.set(1, o);
但它不起作用,即使你避免使用不可表示类型的局部变量。换句话说,即使以下内容也无法编译:list.set(1, list.get(0));
但是您可以通过允许在操作期间捕获类型参数中的通配符类型来添加执行操作的通用辅助方法:static <T> void copyFromTo(List<T> l, int from, int to) {
l.set(to, l.get(from));
}
List<?> list = …
copyFromTo(list, 0, 1); // now works
您也可以将此模式应用于您的案例:
class ComputableInfo {
IComputable<?> computable;
Object config; // Real type is <?>
int result;
ComputableInfo(String id) {
computable = ComputableFactory.createFrom(id);
configureAndCompute(computable);
}
private <T> void configureAndCompute(IComputable<T> computable) {
T typedConfig = computable.configure();
this.config = typedConfig;
this.result = computable.compute(typedConfig);
}
}
这有效,不需要制作 ComputableInfo
通用的。如果您需要捕获类型的时间超过单个方法,例如如果要使用创建的
config
多次,您可以使用封装:class ComputableInfo {
static final class CompState<T> {
IComputable<T> computable;
T config;
CompState(IComputable<T> c) {
computable = c;
}
private void configure() {
config = computable.configure();
}
private int compute() {
return computable.compute(config);
}
}
CompState<?> state;
int result;
ComputableInfo(String id) {
state = new CompState<>(ComputableFactory.createFrom(id));
state.configure();
result = state.compute();
}
}
这样,您仍然可以避免将类型参数导出给 ComputableInfo
的用户。 .
关于java - 告诉编译器一个 <Object> 等价于它想要的 <?>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63935181/