3

我一直面临着一个我不太了解的奇怪现象。我有一个由其他几个类扩展的抽象类。抽象类是一种特殊的集合,它有一个适合它的嵌套抽象迭代器类。每个扩展抽象集合类的类,也都有一个嵌套迭代器类,它扩展了原始抽象迭代器。

抽象类是这样的:

public abstract class AbstractMultiCollection<T> {

    public AbstractMultiCollection() {
    ...
    }

    MultiIterator<T> iterator();

    public abstract class AbstractMultiIterator {
        public AbstractMultiIterator() {
        ...
        }

扩展类是这样的:

public class MajorityMultiCollection<T> extends AbstractMultiCollection<T> {
...
    public MultiIterator<T> iterator() {
        return new MajorityIterator();
    }
    ...     

    public class MajorityIterator extends AbstractMultiIterator {

        public MajorityIterator() {
        super();
        ...
        }

        public T next() {
        ...
        }

简单地说,集合扩展了抽象集合,它们的嵌套迭代器扩展了嵌套的抽象迭代器。

我有两个我不明白的问题,希望得到澄清:

  1. 当我调试我的代码时,“return new MajorityIterator();” 行在 Eclipse 调试器中引发“未找到源”错误和“ClassNotFound”异常以及我不理解的一堆“ClassLoaderExt”异常。
  2. 我注意到每个“MajorityIterator”都有两个“This$0”字段,包含他所属的集合。一开始是空的,但是一旦我调用“super();”就会收到集合 建设者。

我没找到原因,谁能解释一下?提前致谢!

4

2 回答 2

4

实际上有两个this参考是有道理的。大多数人没有意识到的一件事是Java 编译器如何实现非静态嵌套类:

  • 它隐式地添加了一个具有外部类类型的新字段,我们称之为outer$object

  • 它隐式地将外部类对象的新参数添加到所有构造函数以填充该字段。顺便说一句,这意味着内部类的默认构造函数实际上有一个参数,这使得通过反射使用它变得更加复杂。

  • 它隐式地创建具有更广泛可见性的构造函数和方法,以解决任何可访问性问题,例如,如果声明了内部类private

由于该outer$object字段需要与外部类具有相同的类型,因此每次嵌套类从未嵌套在同一外部类中的类继承时都会添加一个。

就个人而言,我倾向于避免使用非静态非匿名内部类,以便将所有内容明确地保留在表面上,而不是让编译器把事情弄得一团糟……

于 2012-12-31T09:16:33.813 回答
3

一个MajorityIterator对象确实有两个this$0字段:

  • 一个(在 中隐式声明MajorityIterator)用于引用的封闭实例MajorityMultiCollection
  • 一个(在 中隐式声明AbstractMultiIterator)用于引用 的封闭实例AbstractMultiCollection。这将在super()调用之前为 null,因为它将在构造函数中设置。

您可能会发现创建这些静态嵌套类更清晰,并改为显式传递对封闭实例的引用 - 我怀疑您只需要一个引用,而且推理起来会更简单。

于 2012-12-31T09:13:52.093 回答