Java 从超类型方法返回子类类型 公共抽象类基类{ T方法1(){ 返回getThis(); } 公共摘要:T getThis(); } 公共类子类扩展了基类{ 公共子类getThis(){ 归还这个; } }

Java 从超类型方法返回子类类型 公共抽象类基类{ T方法1(){ 返回getThis(); } 公共摘要:T getThis(); } 公共类子类扩展了基类{ 公共子类getThis(){ 归还这个; } },java,generics,Java,Generics,如果它只是一个继承级别,我可以执行上面的操作,并在调用method1()时获取子类的引用 如果我有两个层次的继承,比如 public abstract class BaseClass<T extends BaseClass<T>> { T method1(){ return getThis(); } public abstract T getThis(); } public class SubClass extends Ba

如果它只是一个继承级别,我可以执行上面的操作,并在调用method1()时获取子类的引用

如果我有两个层次的继承,比如

public abstract class BaseClass<T extends BaseClass<T>> {

    T method1(){
        return getThis();
    }

    public  abstract T getThis();
}

public class SubClass extends BaseClass<SubClass> {
    public SubClass getThis(){
        return this;
    }
}
公共抽象类子类1扩展了基类{
@凌驾
公共子类1 getThis(){
归还这个;
}
}
公共类SubClass1扩展了子类1{
}

我应该将什么更改为method1和基类,以便在调用method1时可以返回SubSubClass1类型。我不想在没有任何抑制警告的情况下执行此操作,重要的是要了解每个类型参数化类的类型参数都是自己的。特别是,它们(参数本身)不与超类或子类共享。类型参数化的子类通常会有意地与它们的超类共享类型参数值,但这是另一回事

类可以指定它们的超类,但它们不能改变它们的超类自己的继承。因此,如果
子类1
扩展了
基类
,那么
基类
的类
子类1
的类型参数及其每个子类都是
子类1
,因为只有该类才是
子类1
扩展的类

BaseClass
的任何具体子类都必须实现其抽象方法
getThis()
,这需要此类(例如
subclass 1
)将
BaseClass
的类型参数
T
指定为可实例化类型(否则它无法提供返回值)。从层次结构的这一点开始,子类可以使用协变返回类型来缩小由
getThis()
返回的类型,但是它们不能更改由
subclass 1
指定的
BaseClass
类型参数,除非它依赖于
subclass 1
自己的类型参数。例如,这可以干净地编译:

public abstract class SubClass1<T extends SubClass1<T>> extends BaseClass<SubClass1<T>> {
    @Override
    public SubClass1<T> getThis() {
        return this;
    }
}

public class SubSubClass1 extends SubClass1<SubSubClass1> {



}
@HannoBinder的道具,他首先在评论中提出了协变返回类型


注意,如果这里的主要思想是使用一个类型参数来标记
基类
的哪个后代,或者至少有一个上限,那么这是错误的。在这种方法中,类型
BaseClass
并不比类型
SomeSubClass
本身更有意义或表达力。参数化版本的唯一区别在于更难使用。

SubSubClass1
必须是实现
getThis()
的版本,如下所示:

public abstract class BaseClass {
    // ...
    public abstract BaseClass getThis();
}

public abstract class SubClass1 extends BaseClass {
    @Override
    public SubClass1 getThis() {
        return this;
    }
}

public class SubSubClass1 extends SubClass1 {
    @Override
    public SubSubClass1 getThis() {
        return this;
    }
}
公共抽象类基类{
T方法1(){
返回getThis();
}
公共摘要:T getThis();
}
公共抽象类子类1扩展了基类{
}
公共类SubClass1扩展了子类1{
@凌驾
公共子类1 getThis(){
归还这个;
}
}

虽然我不完全清楚,但我有一个问题。在java中,一个类如何一次扩展两个类?我的意思是我们可以在一个类上使用extends关键字两次吗?@TheGuest:它不能直接扩展两个类。但是它可以实现任意多的接口。但是,如果使用
&
@TheGuest查看,则可以使用多个边界限制类型参数。这是一个相当全面的解释。@TheGuest,这个例子不涉及扩展两个类的类。两个“extends”关键字中的一个适用于类型参数
T
,而不是类
子类1
。不确定要实现什么,但可能simple可以做到,不需要genrics。new SubSubsubClass1().method1()仍将返回子类1而不是子类1:这不是OP的意图。考虑这个片段:<代码> BaseCassBC=新子类();bc.getThis()。我理解这个问题,OP想要在编译时获得类型为
subsubsubclass1
bc.getThis()
,但这里不是这样的:它是
BaseClass
,很难说OP的意图是什么,但我想我的答案是他能做的最好的。我更新了一些关于为什么会这样的评论。如果他想要实现的是不可能的,那么这就是你的答案,而不是提供一个稍微不同的问题的答案。基本上,OP希望能够在很好地使用多态性的同时获得类的运行时类型。我已经更新了答案,以解释为什么OP不能得到他似乎在问的问题。我保留了提供对他来说可能可行的替代方案的部分,以及解释为什么他认为他想要的不是一个有用的目标的部分(这提高了提供的替代方案的价值)。
public abstract class BaseClass {
    // ...
    public abstract BaseClass getThis();
}

public abstract class SubClass1 extends BaseClass {
    @Override
    public SubClass1 getThis() {
        return this;
    }
}

public class SubSubClass1 extends SubClass1 {
    @Override
    public SubSubClass1 getThis() {
        return this;
    }
}
public abstract class BaseClass<T> {
    T method1(){
        return getThis();
    }
    public abstract T getThis();
}

public abstract class SubClass1<T> extends BaseClass<T> {
}

public class SubSubClass1 extends SubClass1<SubSubClass1> {
    @Override
    public SubSubClass1 getThis() {
        return this;
    }
}