JavaRush /Курсы /Модуль 2. Java Core /Внутренние классы

Внутренние классы

Модуль 2. Java Core
15 уровень , 0 лекция
Открыта
Вложенные классы - 1

— Привет, Амиго!

— Привет, Элли!

— Сегодня будет очень интересная тема. Я сегодня расскажу о внутренних классах.

Если один класс объявить внутри другого, то такой класс называется внутренним.

Объекты внутренних классов при этом вложены в объекты внешних классов и могут обращаться к переменным внешних классов.

Пример
public class Car
{
 int height = 160;
 ArrayList doors = new ArrayList();

 public Car
 {
  doors.add(new Door());
  doors.add(new Door());
  doors.add(new Door());
  doors.add(new Door());
 } 

class Door()
 {
  public int getDoorHeight()
  {
   return (int)(height * 0.80);
  }
 }
}

Обрати внимание, у класса Door(дверь) есть метод, который возвращает высоту двери – getDoorHeight, этот метод использует переменную height объекта Car.

Вложенные классы - 2

Объект типа Door не может существовать отдельно от объекта типа Car – ведь он использует его переменные. Компилятор незаметно добавляет в конструктор и в класс Door ссылку на объект внешнего класса Car, чтобы методы внутреннего класса Door могли обращаться к переменным и вызвать методы внешнего класса Car.

— Вложенные объекты. Мне все понятно. Судя по картинке тут все элементарно.

— Так и есть. Лишь пара нюансов.

Во внутреннем классе Door имеется ссылка на объект класса Car, поэтому:

1) Нельзя создать объект Door внутри статического метода в классе Car: негде взять ссылку на объект типа Car, который неявно передается в конструктор типа Door.

Правильно Неправильно
public class Car
{
 public static Door createDoor()
 {
 Car car = new Car();
  return car.new Door();
 }

 public class Door
 {
  int width, height;
 }
}
public class Car
{
 public static Door createDoor()
 {
  return new Door();
 }

 public class Door
 {
  int width, height;
 }
}

2) Класс Door не может содержать статические переменные и методы.

Правильно Неправильно
public class Car
{
 public int count;
 public int getCount()
 {
  return count;
 }

 public class Door
 {
  int width, height;
 }
}
public class Car
{

 public class Door
 {
  public static int count;
  int width, height;

  public static int getCount()
  {
   return count;
  }
 }
}

— А если мне нужна общая переменная для всех объектов Door?

Ты всегда можешь объявить ее просто в классе Car – это и будет общая переменная для всех объектов Door, вложенных в объект Car.

3) Обрати внимание, что если внутренний класс объявлен как public, то его объекты можно создавать вне внешнего класса, но объект внешнего класса при этом обязан присутствовать:

Car car = new Car();
Car.Door door = car.new Door();
Car.Door door = new Car().new Door();

4) И еще одно замечание – чуть не забыла.

Т.к. у нас два вложенных объекта, то в методах внутреннего объекта доступно две ссылки this:

public class Car
{
 int width, height;

 public class Door
 {
  int width, height;

  public void setHeight(int height)
  {
   this.height = height;
  } 

  public int getHeight()
  {
   if (height!=0)
    return this.height;
   else 
    return (int)(Car.this.height * 0.8);
  }
 }
}

Я специально объявила в классах одинаковые переменные.

Чтобы обратиться к переменной внешнего класса, когда она скрыта, или к this внешнего класса, достаточно написать «имя класса» точка this:

Как получить доступ к this внешнего (или любого) класса
Car.this
Car.Door.this
Car.Door.InnerClass2.InnerClass3.this

— Т.е. если мы внутри метода внутреннего класса пишем this, то этот this относится к внутреннему классу?

— Да. Именно так.

Как тебе внутренние классы, Амиго?

— Очень интересно. Я бы не сказал, что очень сложно.

Есть много ограничений, но они вполне логичны, когда ты мне объяснила, откуда и зачем они берутся.

А я уже два месяца в практических заданиях постоянно пишу вложенные классы и только сейчас понял, что же я писал на самом деле.

Спасибо за отличный урок, Элли.

— Рада, что тебе понравилось, Амиго.

Комментарии (9)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Сергей Уровень 114
5 апреля 2025
Условия написаны неккоректно
19 декабря 2024
"Есть много ограничений, но они вполне логичны, когда ты мне объяснила, откуда и зачем они берутся." - админы/модераторы, у вас Амиго говорит цветом Элли...
Артём Уровень 112
7 ноября 2024
Задача про рефакторинг и вложенные классы из следующей лекции. Лучше сначала прочитать её, а потом вернуться решать эту задачу.
Руслан Никитин Уровень 109
25 сентября 2024
2) Класс Door не может содержать статические переменные и методы с одним ньюансом, Класс Door может может содержать статические переменные если они final.
Наталья Уровень 107
29 марта 2024
когда-нибудь они научатся писать корректно условия
Олег Уровень 111 Expert
17 мая 2023
"Чтобы обратиться к переменной внешнего класса, когда она скрыта, или к this внешнего класса, достаточно написать «имя класса» точка this: ... — Т.е. если мы внутри метода внутреннего класса пишем this, то этот this относится к внутреннему классу? — Да. Именно так." Только мне кажется, что объяснение не очень логично? Может так: "Для доступа к переменной внешнего класса, которая скрыта внутри анонимного класса, можно использовать ключевое слово "this" в сочетании с именем внешнего класса, за которым следует оператор точки." И "Аналогичным образом можно обратиться к ключевому слову this внешнего класса, используя OuterClass.this. Это может быть полезно, когда необходимо сделать явную ссылку на текущий экземпляр внешнего класса из анонимного класса."
Иван Корниенко Уровень 109
16 марта 2024
Почему анонимного?
Greg Уровень 108 Expert
5 ноября 2022
Как я понял, ограничения касательные статики описанные тут уже не ограничения в 16 версии языка.
Александр Уровень 111 Expert
27 июля 2022
Не знал, что если классу присвоить модификатор final, то он не может быть унаследован