Java 最后一个参数存储在匿名类实例中的什么位置?

Java 最后一个参数存储在匿名类实例中的什么位置?,java,parameters,adapter,final,anonymous-class,Java,Parameters,Adapter,Final,Anonymous Class,我有以下静态工厂方法,可以从int数组中创建列表视图: public static List<Integer> newInstance(final int[] numbers) { return new AbstractList<Integer>() { @Override public Integer get(int index) { return numbers[index]; }

我有以下静态工厂方法,可以从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);

}
公共静态列表newInstance(最终整数[]个){
返回新的AbstractList(){
@凌驾
公共整数get(整数索引){
返回编号[索引];
}
@凌驾
公共整数大小(){
返回数字。长度;
}
};
}
公共静态void main(字符串[]args){
int[]序列={10,20,30};
List List=ListFactory.newInstance(序列);
System.out.println(“列表为”+列表);
}
在《有效的Java》中,Joshua Bloch提到了这一点

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

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

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


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

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

以及
抽象列表
的匿名实现的表示:

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);
    }
}
标记为synthetic的方法和字段由编译器生成,程序员无法访问,但在运行时用于访问int数组。实际上,有一个
val$numbers
字段保存对int数组的最终引用


顺便说一下,您还可以注意到在
Integer-get(int-index)
中从
int
Integer
的装箱,并且为了符合原始(非通用)
列表
接口,会生成一个额外的
对象get(int-index)
方法,该方法将委托给类型安全的
Integer-get(int-index)
实现。

它作为合成字段存储在
抽象列表的匿名类中。您可以使用
javap
实用程序查看它:

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);
}
输出:

val$numbers
true

这与以下问题有关:

Jon Skeet已经对上述问题做出了规定:

创建匿名内部类的实例时,该类中使用的所有变量的值都会通过自动生成的构造函数复制进来。这避免了编译器必须自动生成各种额外类型来保存“局部变量”的逻辑状态


因此,在本例中,int[]数字会自动复制到匿名类中,该类作为合成字段从
AbstractList
扩展而来。

字段[0]
并不总是有效的。“返回的数组中的元素没有排序,也没有任何特定的顺序。”+1,因为您已经回答了OP的问题。@KevinCruijssen感谢您的投票和评论。这只是一个没有显式声明字段的例子。@Andremoni感谢您提到反射和合成字段的概念。感谢您提到javac-d-XD printflat命令,在本例中非常有用!感谢链接到Jon Skeet的答案,这与我的问题非常相关,有助于我理解这个主题。
    Field[] fields = list.getClass().getDeclaredFields();
    System.out.println(fields[0].getName());
    System.out.println(fields[0].isSynthetic());
val$numbers
true