最终参数在哪里存储在匿名类实例中?

时间:2015-12-15 13:22:54

标签: 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];
        }

        @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);

}

在&#34; Effective Java&#34;中,Joshua Bloch提到了这个

  

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

但是,我记得Adapter使用了合成,而匿名列表实现的实例应该使用int []作为成员字段。

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

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

3 个答案:

答案 0 :(得分:7)

您可以使用javac -d . -XD-printflat ListFactory.java来查看编译器如何理解内部类。实际上,您的示例中有两个Java类。 ListFactory(请注意numbers如何传递给ListFactory$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数组。确实有一个val$numbers字段,它保存了对int数组的最终引用。

顺便说一下,您还可以注意intIntegerInteger get(int index)的拳击,以及符合原始(非通用)List界面的额外{{}生成了{1}}方法,该方法委托给类型安全的Object get(int index)实现。

答案 1 :(得分:3)

它作为合成字段存储在Integer get(int index)的匿名类中。您可以使用AbstractList实用程序查看它:

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);
}

输出:

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

答案 2 :(得分:2)

这与问题有关:Why are only final variables accessible in anonymous class?

Jon Skeet已经为上述问题提供了succinct answer

  

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

因此,在这种情况下,int []数字会自动复制到从SELECT * FROM (SELECT symbol_name , (prevclose_val-close_val) AS losers, STR_TO_DATE(current_day, '%d-%M-%Y'), 'weekly' AS `type` FROM historical_data WHERE date_format( STR_TO_DATE(current_day, '%d-%M-%Y'), '%Y%m%d') >= date_format(date_sub(now(), interval 7 day), '%Y%m%d') ORDER BY losers ASC LIMIT 10 ) AS sub_weekly; 扩展为合成字段的匿名类。