为什么在Java中从自绑定泛型返回时需要强制转换
在本例中,我的IDE在return语句中显示编译错误为什么在Java中从自绑定泛型返回时需要强制转换,java,generics,inheritance,casting,Java,Generics,Inheritance,Casting,在本例中,我的IDE在return语句中显示编译错误 public class Base<T extends Base>{ public T get(){ return this; } } 为什么您认为您的this属于T类型?它属于Base类型 尝试运行以下代码,您将得到ClassCastException: public class Main { public static void main(String[] args) {
public class Base<T extends Base>{
public T get(){
return this;
}
}
为什么您认为您的
this
属于T
类型?它属于Base
类型
尝试运行以下代码,您将得到ClassCastException
:
public class Main {
public static void main(String[] args) {
Base<Child> b = new Base<>();
// b.get() returns an instance of Base, not Child (however it's mistakenly cast to Child)
Child1 c = b.get();
}
public static class Base<T extends Base>{
public T get(){
return (T) this;
}
}
public static class Child extends Base {
}
}
公共类主{
公共静态void main(字符串[]args){
基b=新基();
//b.get()返回Base的实例,而不是Child(但是它被错误地强制转换为Child)
child1c=b.get();
}
公共静态类基{
公共部门得不到{
返回(T)这个;
}
}
公共静态类子扩展基{
}
}
此错误的原因与为以下代码创建的错误相同:
public void myMethod(InputStream is) {
ByteArrayInputStream bais = is;
}
public class Base<T extends Base>{
public Base<T> get(){
return this;
}
}
只是泛型。要消除编译器错误,您可以像在代码中那样执行强制转换:
public void myMethod(InputStream is) {
ByteArrayInputStream bais = (ByteArrayInputStream) is;
}
但是,如果传递的inputstream不是ByteArrayInputStream
或派生自它的类,则在运行时这将失败。同样的情况也会发生在您的代码中。除非您只创建Base
的实例,否则在您的示例中调用get
时,强制转换将导致错误:
public class Base<T extends Base>{
public T get(){
return this;
}
}
如果您的目标是返回参数化类型,那么您可能无法这样做。参数化类型本身不是
Base
类中的实例,而是参数化类型。如果这是您所需要的,您可以使用反射获得参数化类型类。转换是不安全的,因为此
(具有类型基
)可能不是T
。我们只知道T
是Base
,而不是相反
在Java中无法表示“自类型”。所以你想做的是不可能的。相反,您可以创建一个抽象方法,强制实现子类提供返回T
的方法:
public class Base<T> {
public abstract T get();
}
public final class Child extends Base<Child> {
public Child get() {
return this;
}
}
公共类基{
公共抽象得不到();
}
公共最终类子扩展基{
公共儿童基金会{
归还这个;
}
}
“Java不是将所有有界泛型替换为有界类型吗?”-你是说擦除吗?擦除限制了运行时可以检查的内容,但它不会阻止编译时的类型安全检查。此
实际上可能不是t
,例如newbase().get()代码>这是一些复杂的代码;你到底想做什么?@fge我更新了问题,这样背景就更清楚了。谢谢。“这个密码安全吗?”不,不安全。考虑到你有一个<代码>类FO扩展了基础< /代码>,接下来将编译:<代码>新脚注().StuPARAMONE(1).StPARAMAM2(1)。但是它将在运行时引起异常。目标是返回参数类型的对象。我更新了问题。你可以阅读为什么需要这个。好的,明白了。我不确定在这种情况下为什么需要使用泛型。IMHO,我看到了一个非常简单的类模型,它使用Base
作为基类,并且不需要使用泛型来达到您解释的目的<代码>此
将始终是实现的类,它既是基
及其子类。原因是,如果没有泛型,当我在“static void main”中对子级调用继承的基方法时,返回类型将是基,我将无法链接在没有外部强制转换的子级中实现的方法。
public class Base<T extends Base>{
public Base<T> get(){
return this;
}
}
public class Base<T> {
public abstract T get();
}
public final class Child extends Base<Child> {
public Child get() {
return this;
}
}