English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
1. Что такое внутренние классы?
Классы, определяемые в классе, называются внутренними классами
public class Out{ class In{ // В этот момент In является внутренним классом } }
2. Почему стоит использовать внутренние классы?
1) Усиление обертки, скрытие внутренних классов в классе-внешнике, не разрешение доступа к внутренним классам других классов
2) Внутренние классы могут повысить читаемость и поддердживаемость кода
3. Классификация внутренних классов
Классификация внутренних классов может быть сравнима с классификацией членских переменных.
Мы можем разделить переменные члена на: переменные класса, переменные примера и локальные переменные в зависимости от различных модификаторов или места определения.
Внутренний класс можно рассматривать как член внешнего класса, поэтому внутренний класс может использовать public/defaul/protected/private и может быть статическим.
Аналогично, внутренний класс также может быть разделен на 4 типа в зависимости от использования различных модификаторов или места определения:
1) Пример внутреннего класса: внутренний класс не использует ключевое слово static
2) Статический внутренний класс: внутренний класс использует ключевое слово static
3) Локальный внутренний класс: внутренний класс, определенный в методе
4) Анонимный внутренний класс: может использоваться один раз, это особый случай внутреннего класса
3.1 Пример внутреннего класса:
1) Определение: Пример внутреннего класса, то есть внутренний класс, не использующий ключевое слово static. Это означает, что пример внутреннего класса принадлежит объекту внешнего класса, а не самому внешнему классу (аналог поля).
2) Создание примера внутреннего класса
// Внешний класс class Outter { // Внутренний класс: не использует ключевое слово static class Inner { } } public class InnerDemo1 { public static void main(String[] args) { // Создание примера внутреннего класса, не использует ключевое слово static, является объектом внешнего класса, поэтому, перед созданием примера внутреннего класса, должен существовать объект внешнего класса Outter out = new Outter(); // Создание объекта внутреннего класса через объект внешнего класса Outter.Inner in = out.new Inner(); } }
3) Характеристики:
a. Из процесса создания внутреннего класса известно, что при наличии объекта внутреннего класса всегда существует объект внешнего класса.
b. Пример внутреннего класса автоматически持有 ссылку на объект внешнего класса, внутренний класс может безусловного доступа к всем членам и методам внешнего класса
Внимание: когда у внутреннего класса члены с одноименными членами или методами внешнего класса, происходит явление скрытия
c. Внешний класс не может напрямую доступа к членам внутреннего класса, необходимо сначала создать объект внутреннего класса, а затем через указатель на этот объект доступа к ним
// Внешний класс class Outter { private String name = "out"; private Integer age = 17; // Внутренний класс: не использует ключевое слово static class Inner { private Integer age = 18; // Явление скрытия, скрыло age внешнего класса Inner() { // Особенности: 1. Внутренний класс может напрямую доступа к членам внешнего класса // 2. Когда у внутреннего класса и внешнего класса есть одноименные поля или методы, происходит явление скрытия System.out.println(name + this.age);// Выводится out18 // Если нужно использовать age внешнего класса, синтаксис: внешняя_класс.this.age System.out.println(Outter.this.age);// Выводится 17 } } }
Обобщение: Кратко говоря, это зависит от области действия переменных, область действия членов внешнего класса составляет весь внешний класс, а внутренний класс находится во внешнем классе (можно рассматривать как поле внешнего класса), внутренний класс естественно может обращаться к внешнему классу. А внешний класс для доступа к членам внутреннего класса можно понять так: члены внутреннего класса принадлежат внутреннему классу, они действительны внутри внутреннего класса, если внутренний класс не существует, его переменные也不会 существовать, поэтому внешний класс не может напрямую обращаться к членам внутреннего класса, необходимо сначала создать объект внутреннего класса, а затем через указатель на этот объект обращаться к нему.
3.2 Статический внутренний класс
1) Определение: Внутренний класс, определенный с использованием статического модификатора. Таким образом, этот внутренний класс принадлежит самому внешнему классу, а не объекту внешнего класса
2) Создание статического внутреннего класса
// Внешний класс class Outter { // Статический внутренний класс: используется статическим модификатором static class Inner { } } public class InnerDemo2 { public static void main(String[] args) { // Поскольку статический внутренний класс принадлежит самому внешнему классу, его можно напрямую обращаться через имя класса внешнего класса (аналог поля) Outter.Inner in = new Outter.Inner(); } }
3) Характеристики:
a. При создании экземпляра внутреннего класса не нужно создавать экземпляр внешнего класса.
b. Статический внутренний класс может напрямую обращаться к статическим членам внешнего класса, если необходимо обращаться к экземплярным членам внешнего класса, необходимо обращаться через экземпляр внешнего класса.
Простое понимание: статические члены принадлежат классу, не статические члены принадлежат объекту, если необходимо обращаться к экземплярным членам внешнего класса (не статическим членам), конечно, сначала нужно сохранить объект внешнего класса. А создание статического внутреннего класса не требует объекта внешнего класса, поэтому, если необходимо обращаться к экземплярным членам внешнего класса, необходимо обращаться через экземпляр внешнего класса.
c. В статическом внутреннем классе можно определять статические и экземплярные члены.
d. Тестовый класс может напрямую обращаться к статическим членам статического внутреннего класса через полное имя класса (аналог поля)
// Внешний класс class Outter { static String name = "outter"; public Integer age = 17; // Статический внутренний класс: используется статическим модификатором static class Inner { Inner() { // Статические внутренние классы могут напрямую обращаться к статическим членам внешнего класса System.out.println(name);// Вывод outter // Доступ к членам экземпляра внешнего класса необходимо производить через экземпляр внешнего класса. System.out.println(new Outter().age);// Вывод 17 } } }
3.3 Локальный внутренний класс (почти не используется)
1) Определение: Внутренний класс, определенный в методе, его область видимости составляет текущий метод, и он находится на одном уровне с локальными переменными, поэтому локальный внутренний класс может использоваться только в методе.
Внимание, локальные внутренние классы, как и локальные переменные в методе, не могут иметь修饰ители public, protected, private и static.
public class InnerDemo3 { public static void main(String[] args) { // Локальный внутренний класс class Inner { } } }
2) Характеристики:
a. Локальные внутренние классы и внутренние классы instances, как и внутренние классы instances, не могут содержать статические члены. (Локальные внутренние классы belong к методу, а статические члены belong к классу)
b. Локальные внутренние классы и внутренние классы instances могут доступа ко всем членам внешнего класса.
c. Локальные внутренние классы должны использовать final для доступа к локальным переменным, в Java 8 это делается автоматически (грамматическая сахар).
Причина: после выполнения метода, текущий стек метода разрушается, все пространство переменных метода разрушается. Но объект внутреннего класса может оставаться в куче памяти, и объект будет продолжать существовать до тех пор, пока он не будет больше не нужен. В этот момент может возникнуть ситуация: внутренний класс пытается получить доступ к не существующему локальному переменной. Чтобы избежать этой проблемы, мы используем final для модификации локальных переменных, тем самым превращая их в константы, постоянно residing в памяти, даже после того, как метод разрушается, переменная все еще остается в памяти, и объект может продолжать существовать.
public class InnerDemo3 { public static void main(String[] args) { int age = 17; final int num = 15; // Локальный внутренний класс class Inner { public void test() { // Ошибка: Cannot refer to a non-final variable age inside an inner class defined in a different method System.out.println(age); System.out.println(num);// правильный } } } }
3.4 Анонимные внутренние классы (используются наиболее часто)
1): Определение: анонимный внутренний класс это локальный внутренний класс без имени, подходящий для использования один раз.
2) Создание анонимного внутреннего класса:
Анонимные внутренние классы themselves не имеют конструктора, но вызывают конструктор суперклассы. Обычно, анонимные внутренние классы используются для наследования от других классов или реализации интерфейсов, не требуя добавления дополнительных методов, просто для реализации или перезаписи методов.
Внимание: анонимные внутренние классы должны наследовать от одной суперклассы или реализовать один интерфейс, но не более одного суперклассы или интерфейса.
// 定义一个接口 interface Person { public void eat(); } public class AnonymousDemo { public static void main(String[] args) { // Использование анонимного внутреннего класса Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } }
4. Подведение итогов
5. Вопрос на интервью
public class Outer { public void someOuterMethod() { // Line 3 } public class Inner { } public static void main(String[] argv) { Outer o = new Outer(); // Line 8 } } /* * Which instantiates an instance of Inner? A. new Inner(); // At line 3 B. new Inner(); // At line 8 C. new o.Inner(); // At line 8 D. new Outer.Inner(); // At line 8 */
Ответ A.new Inner(); эквивалентен this.new Inner(); уже существует объект класса Outer.
line 8 правильный способ, должен быть: o.new Inner();
Вот весь контент статьи. Надеюсь, что контент статьи поможет вам в изучении или работе, и также надеюсь на вашу поддержку呐喊 руководства!
Заявление: содержание этой статьи взято из Интернета, авторские права принадлежат соответствующему автору. Контент предоставлен пользователями Интернета, автоматически загружен, сайт не обладает правами собственности, не прошел редактирование, не несет ответственности за соответствующие юридические последствия. Если вы обнаружите материалы,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (во время отправки письма замените # на @), и предоставьте соответствующие доказательства. Если после проверки подтвердится, что материал является подозрительным, сайт немедленно удалил涉嫌侵权的内容.