假设我已将API方法声明为以下
public class Dummy {
public static class Result<ValueT extends Comparable> {
public ValueT value;
}
public static <ValueT extends Comparable> Result<ValueT>
getResult(Class<? extends Result<ValueT>> ofType) throws Exception {
return ofType.newInstance();
}
}
现在我想依靠Java编译时类型验证来调用它,并且无法找到正确的语法来执行此操作:
尝试:
getResult(Result<Integer>.class)
<-- expected syntax
public static void invokeGetResult() {
Result<Integer> intResult = getResult(Result<Integer>.class);
}
结果
error: <identifier> expected
Result<Integer> intResult = getResult(Result<Integer>.class);
^
getResult(Result.class)
<-- just to try
public static void invokeGetResult() {
Result<Integer> intResult = getResult(Result.class);
}
结果
error: method getResult in class Dummy cannot be applied to given types;
Result<Integer> intResult = getResult(Result.class);
^
required: Class<? extends Result<ValueT>>
found: Class<Result>
reason: cannot infer type-variable(s) ValueT
(argument mismatch; Class<Result> cannot be converted to Class<? extends Result<ValueT>>)
where ValueT is a type-variable:
ValueT extends Comparable declared in method <ValueT>getResult(Class<? extends Result<ValueT>>)
getResult((Class<Result<Integer>>)Result.class)
<-- just to try
public static void invokeGetResult() {
Result<Integer> intResult = getResult((Class<Result<Integer>>)Result.class);
}
结果
error: incompatible types: Class<Result> cannot be converted to Class<Result<Integer>>
Result<Integer> intResult = getResult((Class<Result<Integer>>)Result.class);
^
答案 0 :(得分:0)
如果传递Class<...>
的唯一目的是实例化它,请考虑使用Supplier<...>
。它没有这个问题,也没有任何例外。
以下是一个例子:
class SomeClass extends Result<Integer> {...}
public static <T extends Result<?>> T getResult(Supplier<T> constructor) {
return constructor.get();
}
使用类似:
getResult(SomeClass::new); // Passes the constructor.
答案 1 :(得分:0)
真的不是Class<Result<Integer>>
。 Class
个对象在运行时表示可重新构造的类,并且在运行时只有一个Class
个对象用于类Result
,您可以通过表达式Result.class
获取该对象。输入Class<Result>
。没有Class
个对象代表Result<Integer>
或Result<String>
等。
您可以使用Class<Result>
类型的表达式(您从Result.class
获得)并在其上执行一系列不安全的转换,将其转换为Class<Result<Integer>>
或类似的内容,例如:
`(Class<Result<Integer>>)(Class<?>)Result.class`
但不是不安全。它是不安全的,因为Class
的接口具有某些方法,这些方法基于类的运行时类型操作返回T
(类Class
的类型参数)。例如,Class
有一个方法.cast()
,它检查传递的对象是否是该类的实例,如果不是,则抛出异常,如果是,则返回对象,类型为{ {1}}。如果您调用T
,它将返回Result.class.cast()
,并且该方法确实在运行时检查该对象是Result
。但是如果在Result
类型的表达式上调用.cast()
,它将返回类型Class<Result<Integer>>
,但是该类在运行时无法检查该事物是Result<Integer>
,因为1)这是同一个Result<Integer>
类对象,2)通用信息在运行时不存在。因此,您可能会获得可能不是Result
的{{1}}。
所以基本上,你需要考虑使用这个类对象做什么,以及当你在运行时可以拥有它是一个表示原始对象的类对象时,如何将它作为Result<Integer>
是有意义的。输入Result<Integer>
。
这里有一个方法Class<Result<Integer>>
。我想知道你为什么在这里有通配符。您是否尝试让它接受Result
的子类?因为如果没有,那么唯一可以传入的是唯一的Class<? extends Result<ValueT>>
类对象本身,这意味着参数基本上没有意义,因为它总是可以传入的相同的东西;在这种情况下,你可以摆脱参数,只是做:
Result
如果您要接受Result
的子类,那么您假设所有子类都必须具有无参数构造函数,因为您在其上调用public static <ValueT extends Comparable<? super ValueT>> Result<ValueT>
getResult() throws Exception {
return new Result<ValueT>();
}
,这很糟糕设计。你应该像Jorn Vernee的回答所暗示的那样使用像Result
这样的东西。
答案 2 :(得分:-1)
public class Dummy {
public static class Result<ValueT extends Comparable> {
public ValueT value;
}
public static <ValueT extends Comparable> Result<ValueT>
getResult(Class<? extends Result<ValueT>> ofType) {
return null;
}
}
您可以这样称呼它:
Dummy.Result<Integer> result = Dummy.getResult(new Result<Integer>(){}.getClass());
编译时验证应该适用于此示例,因为您正在创建一个匿名空类,并且可以成功检索它的类型信息。
您也可以在评论中建议@Jorn建议进行类型转换,尽管您的编译器会警告您它是“未经检查的强制转换”。