JavaRush /Java Курсы /Java Multithreading /Вложенные классы

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

Java Multithreading
3 уровень , 3 лекция
Открыта
Вложенные классы - 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 относится к внутреннему классу?

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

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

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

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

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

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

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

Комментарии (112)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Максим Li Уровень 40
19 мая 2024
19.05.2024
Anonymous #3306019 Уровень 36
22 сентября 2023
Не очень понятно к чему в курсе Java комиксы в стиле Крокодила 50-летней давности. Будто для старых дедов, мечтающих о коммунизме, но решивших нарушить свои принципы и выйти на рынок труда, подучив основы Java)
Anonymous #2212601 Уровень 39
25 сентября 2023
хех, да, диссонанс небольшой)
ВК Уровень 36
23 декабря 2024
это современная шутка о том как весь мир захватит Китай. актуально?
Rolik Уровень 41
12 апреля 2023
Из всего вышеперечисленного, чаще всего сталкивался с анонимным внутренним классом.
Сергей Белов Уровень 25
13 декабря 2022
 
Car.Door door = car.new Door(); 
Как же криво смотрится пробел между car.new и Door(). Ощущение что компилятор выругается увидев такое)))
Сергей Удодов Уровень 30
19 августа 2022
Чувак на картинке левую икру перекачал🤔
partiec Уровень 33
25 мая 2023
Это ноги - базуки :)
Alexey Svorkin Уровень 37
10 июня 2022
СМЫСЛ ЭТОЙ КАРТИНКИ?
Вадим Уровень 51
19 июня 2022
1. У одного внешнего объекта может быть несколько внутренних объектов. 2. У разных внешних объектов - разные внутренние объекты, и эти объекты никак не пересекаются. Пример: У одной обычной машины(первого внешнего объекта) свои четыре двери(четыре внутренних объекта), а у другой машины-лимузина(второго внешнего объекта) - свои шесть дверей(шесть внутренних объектов).
Vladimir Shmakov Уровень 37
9 марта 2022
Спасибо ! PS: не правильно в первом примере : public Car { doors.add(new Door()); doors.add(new Door()); doors.add(new Door()); doors.add(new Door()); } class Door() {... должно быть наоборот public Car () [- конструктор, а создание внутреннего класса -class Door {.. без скобок ()
Viter Уровень 38
17 февраля 2023
Наверно специально так написали чтоб замечали такие жесткие ошибки потому как столько лет прошло а ничего не исправили, но это плохой метод обучения так как у кого-то подобные ошибки могут отложится в памяти и потом всплыть как память о корректном коде
Lafaed Уровень 36
6 марта 2023
"ошибки могут отложится в памяти" Мне это не грозит - хорошо что я тупой и ничего не понял !
antlantis Уровень 41
8 января 2022
Товарищи, подскажите пожалуйста, я немного не понял пункт 4. лекции " 4) И еще одно замечание – чуть не забыла. Т.к. у нас два вложенных объекта, то в методах внутреннего объекта доступно две ссылки this" два вложенных объекта? а где они? один объект Door есть. всё вроде бы) и если не сложно, подскажите пожалуйста, " return (int)(Car.this.height * 0.8) " - это объект класса Door ?
Дмитрий Уровень 35
11 января 2022
Я так понял, что в данном случае речь идет о переменных height. В методе getHeight() класса Door к этой переменной можно обратиться через this.height, если нужна переменная класса Door, или Car.this.height, если нужна переменная класса Car.
Ars Уровень 41
22 февраля 2022
Да, вложенный объект один. > подскажите пожалуйста, " return (int)(Car.this.height * 0.8) " - это объект класса Door ? В этой строке обращение к переменной height экземпляра класса Car.
Kurama Уровень 50
3 ноября 2022
this.поле в методе Car "ссылается" на поле класса Car (как обычно), а this.поле в методе Door "ссылается" на поле класса Door (логично). Door внутри Car, поэтому, чтобы "обратиться" именно к полю класса Car из метода класса Door, нужно писать Car.this.поле Пример:

public class Car {
    int height;     // Поле класса Car

    public class Door {
        int height;     // Поле класса Door 

        public void setHeight(int height) {
            this.height = height;    // Обычное присваивание полю класса Door 
            Car.this.height = (int) (height/0.8);    // Присваивание полю внешнего класса Car
        }
    }
}
Если в классе Door сделать ещё один внутренний класс Window, то из метода класса Window "доступ" к полю класса Window осуществлялся бы как обычно - через this.поле; к полю "самого" внешнего класса Car - через Car.this.поле; а к полю "промежуточного" класса Door - через Car.Door.this.поле Если я ничего не перепутал
NEW GEN Уровень 35
10 августа 2021
а вот тут совпало если вы будете как робот 300 часов в месяц изучать java эта фраза для вас совпадет))) А я уже два месяца в практических заданиях постоянно пишу вложенные классы и только сейчас понял, что же я писал на самом деле.