为什么在Java中从自绑定泛型返回时需要强制转换

为什么在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) {

在本例中,我的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) {
        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;
    }
}