[英]generic wildcard is accepted but not Type T
对于以下情况,假设AModel.class扩展了ABCModel,则情况1
案例1有效
public static Class<? extends ABCModel> getModel(String objectModel) {
if(objectModel.equalsIgnoreCase("")) {
return AModel.class;
}
return null;
}
情况2(引发编译错误)
public static <T extends ABCModel> Class<T> getModel(String objectModel) {
if(objectModel.equalsIgnoreCase("")) {
return AModel.class;
}
return null;
}
目的不只是一样吗?
在第二种情况下,您将约束类型变量T
来扩展ABCModel
并承诺返回Class<T>
。 但是T
不会在任何地方绑定,因此在编译时无法确定T
是什么。
示例1的不同之处在于返回类型定义为Class<? extends ABCModel>
Class<? extends ABCModel>
,其上限为ABCModel
。
在第二种情况下,在编译时绑定T
一种方法是将其作为方法的参数,例如:
public static <T extends ABCModel> Class<T> getModel(String objectModel, Class<T> clazz) {
现在, T
是根据传递给方法的参数进行绑定的(这就是为什么您看到许多使用Class
参数的通用方法的原因)。
当然,这对您的方法无济于事,因为您想要检索Class
,如果您已经将其传递进来,则没有必要。但这仅意味着您应该使用示例1或修复您的设计。
两者有很大的不同。
在第一种情况下,你将一些类,它扩展ABCModel
, 你决定 。 调用者不能假定有关类型参数的身份的任何信息。
在第二种情况下,您保证将返回T
类,无论调用者想要什么T
! 调用者可以使用您想要的 T
来调用您的方法,在这种情况下,您的方法必须神奇地返回该类型参数的类,而根本不知道T
是什么。 这意味着您的方法必须同时返回具有相同代码的Class<AModel>
和Class<BModel>
等。 这显然是不可能的(除非它总是返回null
)。
解决问题的方法取决于您的用例:
如果您的方法确定了特定类型并返回了它,则第一个示例就是正确的方法。 尝试进一步指定返回类型没有用,因为如果调用者需要指定该类型,则无法回答问题“哪个子类型”。
但是,如果您的方法有多个调用,并且每个调用将始终返回期望的子类型,则通用返回类型很有用。 在这种情况下,您的呼叫者将知道特定的返回类型,并可以使用该参数来避免在呼叫站点上进行强制转换。 您需要做的就是在实现中进行转换: return (Class<T>) AModel.class;
第一种情况示例:
// The caller does not know the return type, so a simple unknown type is appropriate
Class<?> determineType(Object myObject) {
return myObject.getClass();
}
第二种情况示例:
// The caller will already know that a property named 'street' will be of type String, so he can invoke <String>getTypedProperty("street") and avoid having to cast himself
<T> T getTypedProperty(String name) {
return (T) genericPropertyStore.get(name);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.