Передача окончательных переменных анонимным классам - PullRequest
19 голосов
/ 19 сентября 2011

В окончательной переменной, передаваемой анонимному классу через конструктор , Джон Скит отметил, что переменные передаются в экземпляр анонимного класса через автоматически сгенерированный конструктор.Почему я не смогу увидеть конструктор, использующий отражение в этом случае:

public static void main(String... args) throws InterruptedException {
final int x = 100;
new Thread() {
    public void run() {
        System.out.println(x);      
        for (Constructor<?> cons : this.getClass()
                .getDeclaredConstructors()) {
            StringBuilder str = new StringBuilder();
            str.append("constructor : ").append(cons.getName())
                    .append("(");
            for (Class<?> param : cons.getParameterTypes()) {
                str.append(param.getSimpleName()).append(", ");
            }
            if (str.charAt(str.length() - 1) == ' ') {
                str.replace(str.length() - 2, str.length(), ")");
            } else
                str.append(')');
            System.out.println(str);
        }
    }

}.start();
Thread.sleep(2000);

}

Вывод:

100
constructor : A$1()

Ответы [ 2 ]

28 голосов
/ 19 сентября 2011

В данном случае это потому, что 100 - это постоянная Это запекается в вашем классе.

Если вы измените x на:

final int x = args.length;

... тогда вы увидите Test$1(int) в выводе. (Это несмотря на то, что это не объявлено явно. И да, захват большего количества переменных добавляет параметры в конструктор.)

17 голосов
/ 19 сентября 2011

Вот что ваша программа печатает в моей системе:

100
constructor : A$1()

Итак, конструктор есть.Тем не менее, это без параметров.Глядя на разборку, получается, что компилятор выясняет, что ему не нужно передавать x в run(), поскольку его значение известно во время компиляции.

Если я изменю код следующим образомитак:

public class A {

    public static void test(final int x) throws InterruptedException {
        new Thread() {
            public void run() {
                System.out.println(x);
                for (Constructor<?> cons : this.getClass()
                        .getDeclaredConstructors()) {
                    StringBuilder str = new StringBuilder();
                    str.append("constructor : ").append(cons.getName())
                            .append("(");
                    for (Class<?> param : cons.getParameterTypes()) {
                        str.append(param.getSimpleName()).append(", ");
                    }
                    if (str.charAt(str.length() - 1) == ' ') {
                        str.replace(str.length() - 2, str.length(), ")");
                    } else
                        str.append(')');
                    System.out.println(str);
                }
            }

        }.start();
        Thread.sleep(2000);
        }

    public static void main(String[] args) throws InterruptedException {
        test(100);
    }

}

Теперь генерируемый конструктор:

constructor : A$1(int)

Единственным аргументом является значение x.

...