Как стать автором
Обновить

Рекурсивно вложенные классы

Время на прочтение1 мин
Количество просмотров4.5K
Только что наткнулся на интересную особенность вложенных классов в Java — их можно вкладывать друг в друга рекурсивно и бесконечно!



public class Main  {
    private Main() {}

    class Test extends Main {
        {
            System.out.printf("This: %h\nEnclosed in: %h\n", this, Main.this); 
            System.out.printf("Main.this is instance of %s\n\n" , Main.this.getClass());
        }
    }

    public static strictfp void main(String... args) {
        new Main().new Test().new Test().new Test();
    }
}


Можно ожидать что оба инстанса класса Test будут ссылаться на включающий их класс Main. Однако, если скомпилировать и запустить получается интересная картина

This: 6665e41
Enclosed in: 2ab600af
Main.this is instance of class Main

This: 796686c8
Enclosed in: 6665e41
Main.this is instance of class Main$Test

This: 3a1af2bc
Enclosed in: 796686c8
Main.this is instance of class Main$Test



То есть Main.this в последних двух экземплярах имеет тип Main$Test, а сами экземпляры ссылаются друг на друга, выстраиваясь в цепочку!

Эта особенность наталкивает на мысли о более эффективной реализации LinkedList. Вот только интересно где JVM хранит ссылку на включающий класс. Если же ссылка неявно является дополнительным полем вложенного класса, то по памяти реализации будут одинаковыми. Но если память под эту ссылку резервируется для всех классов, то игра за лишние восемь байт на элемент стоит свеч :)

UPD: оказывается все решается по первому варианту — компилятор вводит синтетические поля. Так что выигрыша не получится — та ссылка, что используется в LinkedList.Node просто будет синтетической
Теги:
Хабы:
+3
Комментарии16

Публикации

Истории

Работа

Java разработчик
358 вакансий

Ближайшие события