自引用泛型并返回自己的实例

时间:2018-10-04 18:10:32

标签: java generics

我有一个位置和一个处理位置的处理器。给定位置,客户端可以请求该位置的处理器。我实现了Location,如下所示:

public abstract class Location<SELF extends Location<SELF>> {
    ...

    public Processor<SELF> processor() {
        return new Processor(this);
    }
}

我正在创建和使用Location中的子类,而从未直接使用Location

public class SecretLocation extends Location<SecretLocation> {
   ...
}

我需要处理器上的类型安全,因此只能提供(属于此具体秘密位置类实例的)引用(此处省略),因此使用SELF和子类,并提供类型化的{{1 }}处理。

现在,我想实现Location,如下所示:

Processor

但是使用此实现,public class Processor<L extends Location<L>> { private final L location; public Processor(L location) { this.location = location; } public L location() { return location; } ... } 中的new Processor(this)无效。我找到了两种方法来解决此问题,但我不确定哪种方法最好:

  • Location中使用new Processor(this)而不是new Processor<>(this),因此基本上禁用了泛型。

  • 在构造函数中接受Location而不是Location<L>,并在L中接受成员变量。结果是Processor中的getter location现在必须返回Processor而不是上面的Location<L>。不利之处在于,在L上创建处理器时,processor.location()现在永远不会再返回SecretLocation,而只会返回SecretLocation。这有点草率,因为现在我再也无法通过处理器取回Location<SecretLocation>

作为参考,这是我的第二个解决方案:

SecretLocation

还有什么更好的选择吗?

1 个答案:

答案 0 :(得分:3)

在这种情况下,最直接的解决方案可能是这样的:

public abstract class Location<SELF extends Location<SELF>> {
    ...

    public Processor<SELF> processor() {
        return new Processor<>( self() );
    }

    protected abstract SELF self();
}

public class SecretLocation extends Location<SecretLocation> {
    ...

    @Override
    protected SecretLocation self() { return this; }
}

问题是给定的界限实际上并未将type参数限制为this的类型,例如,以下类将编译:

class BadLocation extends Location<SecretLocation> {}

另一种解决方案是使用未经检查的演员表:

return new Processor<>((SELF) this);

这也将起作用,但是如BadLocation所示,没有真正的限制,this实际上是SELF的对象。 (但是,对于abstract方法解决方案,子类不必从该方法返回this,因此,在保证正确性方面,都不是完美的解决方案。)