如何引用接口在Java中实现的类类型?

我遇到了我正在制作的程序中的接口问题。 我想创建一个接口,它的一个方法接收/返回对自己对象类型的引用。 它是这样的:

public interface I { ? getSelf(); } public class A implements I { A getSelf() { return this; } } public class B implements I { B getSelf() { return this; } } 

我不能使用“I”,它是“?”,因为我不想返回对接口的引用,而是类。 我搜索并发现Java中没有办法“自我引用”,所以我不能只用“?”来代替它。 在“自我”关键字或类似的示例中。 实际上,我想出了一个类似的解决方案

 public interface I { SELF getSelf(); } public class A implements I { A getSelf() { return this; } } public class B implements I { B getSelf() { return this; } } 

但它看起来似乎是一种解决方法或类似的东西。 还有另一种方法吗?

在扩展接口时,有一种方法可以强制使用自己的类作为参数:

 interface I> { SELF getSelf(); } class A implements I { A getSelf() { return this; } } class B implements I { // illegal: Bound mismatch A getSelf() { return this; } } 

这甚至在编写generics类时也有效。 唯一的缺点:必须将thisSELF

正如安德烈马卡罗夫在下面的评论中指出的那样,在编写generics类时这并不能可靠地工作。

 class A> { SELF getSelf() { return (SELF)this; } } class C extends A {} // Does not fail. // C myC = new C(); // B myB = myC.getSelf(); // <-- ClassCastException 

Java支持协变返回类型,因此这是一个选项。 利用AB都来自Object的事实:

 public interface I { Object getSelf(); // or I, see below } public class A implements I { A getSelf() { return this; } } public class B implements I { B getSelf() { return this; } } 

关键是A.getSelf()B.getSelf()都是B.getSelf()的合法覆盖,即使它们的返回类型不同。 这是因为每个A都可以 Object 一样对待,因此返回类型与基本函数的类型兼容 。 (这称为“协方差”。)

实际上,由于AB也是从I派生的,因此出于同样的原因可以用I替换Object

协方差通常是一件好事:拥有I类接口对象的人可以调用getSelf()并获得另一个接口,这就是她需要知道的全部内容。 另一方面,已经知道他有A对象的人可以调用getSelf()并实际获得另一个A对象。 附加信息可用于获取更具体的派生类型,但缺少该信息的人仍可获得接口基类规定的所有内容:

 I x = new A(); A y = new A(); I a = x.foo(); // generic A b = y.foo(); // we have more information, but b also "is-an" I A c = (A)x.foo(); // "cheating" (we know the actual type) 

我想知道是否有其他方法可以这样做?

可以按如下方式编写它:

 public interface I { I getSelf(); } 

然后将结果转换为您想要的类型。 您现有的AB课程将按原样运作。

(这是返回类型协方差的一个示例。在Java 5中添加了对返回类型协方差的支持。此方法将在较旧的JDK中提供编译错误。)

使用generics的替代版本(您称之为解决方法,但事实并非如此)允许您避免显式类型转换。 但是,在生成的代码中存在隐式类型转换,并且在运行时…除非JIT编译器可以优化它。

没有更好的选择,AFAIK。

正如其他人所说,您可以覆盖实现类中的返回类型:

 public interface I { public I getSelf(); } public class A implements I { @Override public A getSelf() { return this; } } 

但是,我有两个“为什么”的问题:

1:为什么要接口返回实现对象? 它似乎违背了接口和inheritance的一般思想。 你能举例说明如何使用它吗?

2:无论如何,你为什么要这个function? 如果a.getSelf()== a,为什么不使用?