最终参数存储在匿名类实例中的什么位置?

我有以下静态工厂方法,用于从 int 数组创建列表视图:

public static List<Integer> newInstance(final int[] numbers) {
    return new AbstractList<Integer>() {

        @Override
        public Integer get(int index) {
            return numbers[index];
        }

        @Override
        public int size() {
            return numbers.length;
        }
    };
}


public static void main(String[] args) {
    int[] sequence = {10, 20, 30};
    List<Integer> list = ListFactory.newInstance(sequence);
    System.out.println("List is "+list);

}

在“有效的Java”中,Joshua Bloch提到了这一点。

作为适配器,允许将 int 数组视为整数实例的列表。

但是,我记得适配器使用组合,匿名列表实现的实例应使用int[]作为成员字段。

如果 int[] 输入参数不是匿名列表实现的成员字段,则它究竟存储在哪里?

如果有人可以提供一些见解或一些链接来寻找更多信息,我将不胜感激。


答案 1

您可以使用 来查看编译器如何理解内部类。实际上,您的示例中有两个 Java 类。(注意如何传递给 的构造函数):javac -d . -XD-printflat ListFactory.javaListFactorynumbersListFactory$1

public class ListFactory {

    public ListFactory() {
        super();
    }

    public static List newInstance(final int[] numbers) {
        return new ListFactory$1(numbers);
    }
}

和匿名实现的表示:AbstractList

class ListFactory$1 extends AbstractList {
    /*synthetic*/ final int[] val$numbers;

    ListFactory$1(/*synthetic*/ final int[] val$numbers) {
        this.val$numbers = val$numbers;
        super();
    }

    @Override()
    public Integer get(int index) {
        return Integer.valueOf(val$numbers[index]);
    }

    @Override()
    public int size() {
        return val$numbers.length;
    }

    @Override()
    /*synthetic*/ public Object get(/*synthetic*/ int index) {
        return this.get(index);
    }
}

标记为综合的方法和字段由编译器生成,程序员无法访问,但在运行时用于访问 int 数组。实际上,有一个字段包含对 int 数组的最终引用。val$numbers

顺便说一句,您还可以注意到从到 in 的装箱,并且为了符合原始(非泛型)接口,会生成一个额外的方法,该方法委托给类型安全的实现。intIntegerInteger get(int index)ListObject get(int index)Integer get(int index)


答案 2

它作为合成场存储在 的匿名类中。您可以使用实用程序查看它:AbstractListjavap

final class q34290420.Test$1 extends java.util.AbstractList<java.lang.Integer> {
  final int[] val$numbers;   // here
  q34290420.Test$1(int[]);
  public java.lang.Integer get(int);
  public int size();
  public java.lang.Object get(int);
}

此外,您可以通过反射发现它:

    Field[] fields = list.getClass().getDeclaredFields();
    System.out.println(fields[0].getName());
    System.out.println(fields[0].isSynthetic());

输出:

val$numbers
true