繁体   English   中英

接受通用通配符,但不接受T型

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM