JavaRush /Java блог /Random UA /Рівень 24. Відповіді на запитання до співбесіди на тему р...
zor07
31 рівень
Санкт-Петербург

Рівень 24. Відповіді на запитання до співбесіди на тему рівня

Стаття з групи Random UA
Рівень 24. Відповіді на запитання до співбесіди на тему рівня - 1
  1. На що компілюються анонімні внутрішні класи?

    Анонімні внутрішні класи компілюються у файли внешнийКласс$n.class. На місці зовнішнього класу, відповідно, назва класу, що обрамляє, всередині якого описується анонімний внутрішній клас. На місці n - число від 1 до кількості анонімних класів.

  2. Чи можна наслідувати внутрішні класи?

    Наслідувати внутрішні класи від інших можна.

    Спадкування від внутрішнього класу виходить трохи складніше, ніж звичайне, оскільки конструктор внутрішнього класу пов'язується з посиланням на зовнішній об'єкт. Проблема полягає в тому, що «приховане» посилання на об'єкт об'ємного зовнішнього класу має бути ініціалізоване, а у похідному класі більше не існує об'ємного об'єкта за умовчанням. Для явної вказівки об'ємного зовнішнього об'єкта застосовується спеціальний синтаксис:

    //: innerclasses/InheritInner.java
    // Наследование от внутреннего класса.
    
    class WithInner {
      class Inner {}
    }
    
    public class InheritInner extends WithInner.Inner {
      //! InheritInner() {} // He компаборуется
      InheritInner(WithInner wi) {
        wi.super();
      }
      public static void main(String[] args) {
        WithInner wi = new WithInner();
        InheritInner ii = new InheritInner(wi);
      }
    }

    Тут клас InheritInnerрозширює лише внутрішній клас, а чи не зовнішній. Але коли справа доходить до створення конструктора, пропонований за замовчуванням конструктор не підходить і ви не можете просто передати посилання на зовнішній об'єкт. Необхідно включити у тіло конструктора вираз посиланняНаОбъемлющийКласс.super();у тілі конструктора. Воно забезпечить посилання, і програма відкомпілюється.

  3. Чи можна наслідувати анонімні внутрішні класи?

    Описуючи анонімний клас, ми вже успадковуємося від якогось класу або реалізуємо якийсь інтерфейс. До анонімних класів безпосередньо не можна застосувати слова extends або implements, але ніхто не заважає заздалегідь підготуватися і розширити потрібний інтерфейс, який будемо реалізовувати за допомогою анонімного класу. Приклад у коді нижче.

    import java.awt.event.WindowListener;
    
    public class TestExtendAnonym {
        private interface MyInterface extends Runnable, WindowListener {
        }
    
        Runnable r = new MyInterface() {
        ...
        //Пример того як реализовать 2 и более интерфейса в анонимном классе
        };
    }

    Спадкуватись від анонімного класу не можна.

  4. Чи можна перевизначати внутрішні класи?

    Перевизначення внутрішнього класу, ніби він був ще одним методом зовнішнього класу, фактично не має жодного ефекту:

    //: innerclasses/BigEgg.java
    // Внутренний класс нельзя переопределить
    // подобно обычному методу,
    import static net.mindview.util.Print.*;
    
    class Egg {
      private Yolk y;
      protected class Yolk {
        public Yolk() { print("Egg.Yolk()"); }
      }
      public Egg() {
        print("New Egg()");
        y = new Yolk();
      }
    }
    
    public class BigEgg extends Egg {
      public class Yolk {
        public Yolk() { print("BigEgg.Yolk()"); }
      }
      public static void main(String[] args) {
        new BigEgg();
      }
    }

    Висновок:

    New Egg()
    Egg.Yolk()

    Стандартний конструктор автоматично синтезується компілятором, а в ньому викликається конструктор за замовчуванням з базового класу. Можна подумати, що з створенні об'єкта BigEggповинен використовуватися «перевизначений» клас Yolk, але не зовсім, як з результату роботи програми.

    Цей приклад показує, що з успадкування від зовнішнього класу нічого особливого з внутрішніми класами немає. Два внутрішні класи - зовсім окремі складові, з незалежними просторами імен. Іншими словами, не можна.

  5. Які обмеження мають локальні класи?

    Спочатку згадаємо, що таке локальний клас. Це клас, описаний у блоці коду, тобто по-простому між лапок {}. Найчастіше ці лапки є тілом методу. Але можуть бути і просто блоком, статичним блоком, тілом if-ов, циклів тощо.

    Локальний клас наділений особливостями внутрішніх класів, але має відмінні риси, а саме:

    1. він має доступ лише до фінальних полів та аргументів обрамляючого методу, а також до всіх полів обрамляючого класу, у тому числі приватних та статичних;
    2. локальний клас видно і може створюватися лише у блоці, у якому описано;
    3. локального класу не ставиться модифікатор доступу;
    4. неспроможна мати статичних полів, методів, класів (крім фінальних);
    5. локальний клас, оголошений у статичному блоці, може звертатися лише до статичних полів зовнішнього класу.

    Але! Починаючи з Java8, ми можемо звертатися в локальних класах до не фінальних локальних змінних, якщо вони не були змінені до моменту ініціалізації класу. Також тепер стало можливим звернення до фінальних параметрів методу.

  6. Чи може внутрішній анонімний клас містити статичні методи?

    Ні. У Анонімних внутрішніх класів, як і внутрішніх класів може бути статичних полів, методів. (Згадаймо, що анонімні класи компілюються у звичайні внутрішні, а ті, у свою чергу, пов'язані з об'єктом класу, що оточує)

  7. Чи можна створити об'єкт внутрішнього класу, якщо зовнішній клас має лише privateконструктор?

    Маючи подібний код:

    public class PrivateConst {
        private PrivateConst() {}
        public class InnerClass{
            public void f(){
                System.out.println("hello");
            }
       }
    }

    Безпосередньо, в іншому класі (поза обрамляючим), звичайно, створити об'єкт InnerClassнаступним способом не вийде:

    PrivateConst.InnerClass priv = new PrivateConst().new InnerClass();

    Але! Що якщо у нас є метод, що повертає екземпляр

    PrivateConst:public class PrivateConst {
        private static PrivateConst instance;
        private PrivateConst() {}
    
        public static PrivateConst getInstance(){
            instance = new PrivateConst();
            return instance;
        }
    
        public class InnerClass{}
    }

    У цьому випадку приватний конструктор нам не перешкода для створення об'єкту InnerClass. Також ми без проблем зможемо створювати його в методах та інших внутрішніх класах, що належать PrivateConst. Відповідь — можна, якщо в якийсь спосіб нам вдасться отримати об'єкт класу, що обрамляє.

  8. Чи можна оголошувати внутрішні класи private?

    Так можна.

    PS Обгрунтування так і не знайшов, але на філософії java зустрічалися такі приклади. Плюс IDE не свариться. Буду вдячний за обґрунтування, але припускаю, що в цьому плані внутрішній клас нічим не відрізняється від звичайного класу.

  9. Чи можна оголошувати анонімні внутрішні класи private?

    Аналогічно (у плані знайшов обгрунтування). Можна оголосити privateзмінну від типу якої успадковується наш анонімний клас.

  10. Скільки у класу максимально можливо внутрішніх класів?

    Наскільки завгодно багато. Обмеження особливості ОС та довжини імені файлів.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ