我的问题很理论......这是Class.asSubclass(Javadoc)的签名:
public <U> Class<? extends U> asSubclass(Class<U> clazz)
Run Code Online (Sandbox Code Playgroud)
为什么返回类型中使用了通配符泛型?根据我对泛型的理解,更好的签名可能是:
public <U> Class<U> asSubclass(Class<U> clazz)
Run Code Online (Sandbox Code Playgroud)
因为你可以肯定演员
Class<? extends U>
Run Code Online (Sandbox Code Playgroud)
更简单
Class<U>
Run Code Online (Sandbox Code Playgroud)
Bloch在他的书"Effective Java"中建议(第137页,第28项):
不要将通配符类型用作返回类型.它不会为您的用户提供额外的灵活性,而是迫使他们在客户端代码中使用通配符类型.
这个选择背后的原因是什么?我错过了什么?非常感谢你提前.
编辑: 正如@egelev建议的那样,我确实可以用另一种方式表达我的问题......事实上,"按原样"返回输入参数将毫无意义.所以真正的问题是:与普通的强制转换相比,Class.asSubclass方法的真正用处是什么?如果出现强制转换问题,两者都会抛出ClassCastException.
可能已添加它以避免在特定情况下未经检查的转换:当您将asSubclass方法的结果直接传递给另一个请求约束类型参数的方法时,如此处(取自Effective Java,第146页):
AnnotatedElement element;
...
element.getAnnotation(annotationType.asSubclass(Annotation.class));
Run Code Online (Sandbox Code Playgroud)
上述方法的签名是:
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
Run Code Online (Sandbox Code Playgroud)
在我看来,asSubclass方法只是一种方法来做一个(事实上!)未经检查的强制转换没有正确的编译器警告...
这最终重新提出我以前的问题:签名
public <U> Class<U> asSubclass(Class<U> clazz)
Run Code Online (Sandbox Code Playgroud)
同样有效(即使很奇怪,我也承认)!它将与getAnnotation示例完全兼容,并且不会限制客户端代码强制它使用无意义的通配符泛型.
编辑2: 我认为我的一般问题已经解决了; 非常感谢你.如果有人有关于asSubclass签名正确性的其他好例子,请将它们添加到讨论中,我希望看到一个完整的例子,使用asSubclass和我的签名,显然不起作用.
我正在阅读本书的第二版,第36页.我不了解simmetry问题的解决方案:
@override public boolean equals(Object o) {
return o instanceof CaseInsensitiveString &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
Run Code Online (Sandbox Code Playgroud)
如果我有,CaseInsensitiveString cis= new CaseInsensitiveString("hello")并且String s="hello"这种行为是非对称的,因为s.equals(cis)
是真的,但是cis.equals(s)
是假的......
我错过了什么?