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

Недавно вы узнали, что бывают статические переменные и статические методы, но, оказывается, бывают еще и статические классы. Но начнем немного издалека.

В языке Java вполне можно объявлять классы внутри классов. И даже классы внутри классов, которые внутри классов внутри классов. Выглядит это все очень просто:

class ВнешнийКласс
{
   переменные класса
   методы класса

   class ВнутреннийКласс
   {
      переменные класса
      методы класса
   }
}

Просто объявляем один класс внутри другого — и все.

Пример:

public class Solution
{
   static ArrayList<Point> points = new ArrayList<Point>();

   public static void main(String[] args)
   {
      Point point = new Point();
      point.x = 100;
      point.y = 200;
      points.add(point);
   }

   static class Point
   {
      int x;
      int y;
   }
}

Внутренние классы бывают статические и нестатические. Статические классы еще называют вложенными (static nested class), нестатические просто называют внутренними классами (inner class).


undefined
12
Задача
Java Syntax Pro, 12 уровень, 4 лекция
Недоступна
Двигатель — сердце автомобиля
Двигатель — сложный механизм, для описания которого недостаточно обычной переменной. В классе Car создай внутренний класс (inner class) Engine. В классе Engine создай boolean поле isRunning, которое принимает значение true, если двигатель запущен, и false в противном случае. Также в этот класс добав

2. Статические классы

Статические вложенные классы можно использовать вне своего родительского класса. Если у такого класса стоит модификатор доступа public, его можно использовать в любом месте программы. Такие классы фактически ничем не отличаются от любого обычного класса. Хотя есть пара отличий.

Имя класса

Если вы хотите обратиться к статическому вложенному классу не из его класса-родителя, а из другого места в программе, вам нужно будет указать имя класса: оно состоит из имени класса родителя и имени вложенного класса. Общий вид этого имени такой:

КлассРодитель.ВложенныйКласс

Примеры:

Класс родитель Вложенный класс Полное имя вложенного класса
com.javarush.Solution
Point
com.javarush.Solution.Point
java.util.Map
Entry
java.util.Map.Entry
java.util.Files
DirectoryStream
java.util.Files.DirectoryStream
java.nio.WindowsPath
Closeable
java.nio.WindowsPath.Closeable

Если вложенный класс имеет свой вложенный класс, их имена просто склеиваются через точку.

Типичный пример вложенного класса в JDK — это класс Entry внутри класса Map. Если вы хотите получить множество пар элементов из объекта HashMap, то метод entrySet() вернет вам множество пар типа Set<Map.Entry>.

Вот запись Map.Entry — это и есть внешний и внутренний классы.

Создание объекта

Создать объект вложенного статического класса очень легко. Выглядит это так:

КлассРодитель.ВложенныйКласс имя = new КлассРодитель.ВложенныйКласс();

Все, как и с обычными классами, только имя двойное.

Обращение к статическим методам

Если у статического класса есть статические методы, обращаться к ним можно точно так же, как к статическим методам обычных классов (только имя класса теперь двойное).

КлассРодитель.ВложенныйКласс.статическийМетод();

Обращение к статическим переменным

Обращаться к публичным статическим переменным вложенного класса тоже легко:

КлассРодитель.ВложенныйКласс.имяСтатическойПеременной

undefined
12
Задача
Java Syntax Pro, 12 уровень, 4 лекция
Недоступна
Утильный калькулятор
Давай проведем рефакторинг кода: вынесем отдельно утильные методы. Для этого создай внутренний статический (вложенный) класс Calculator и перенеси в него методы add, subtract, multiply и divide. Не забудь подкорректировать их вызовы.

3. Особенности статических классов

Статические внутренние классы меньше всего стоило бы называть статическими. Они ведут себя точно так же, как обычные классы. Никаких ограничений на обращение к ним из нестатических методов нет.

Если вы работаете с внутренним статическим классом внутри его класса-родителя, вообще не заметите никакой разницы с тем, если бы этот внутренний класс был бы самым обычным классом (не вложенным и не статическим).

Пример:

Внутренний статический класс Point Обычный класс Point
public class Solution
{
   static ArrayList<Point> points;

   public static void main(String[] args)
   {
      Point point = new Point();
      point.x = 100;
      point.y = 200;
      points = new ArrayList<Point>();
      points.add(point);
   }

   static class Point
   {
      int x;
      int y;
   }
}
public class Solution
{
   static ArrayList<Point> points;

   public static void main(String[] args)
   {
      Point point = new Point();
      point.x = 100;
      point.y = 200;
      points = new ArrayList<Point>();
      points.add(point);
   }
}

class Point
{
   int x;
   int y;
}

Если вы возьмете какой-то вложенный статический класс и вынесете его из его класса родителя, все, что изменится, так это то, что новый класс потеряет способность обращаться к private static переменным и методам бывшего класса-родителя.

Пример:

Внутренний статический класс Point Обычный класс Point
public class Solution
{
   private static ArrayList<Point> points;

   static class Point
   {
      int x;
      int y;

      public static void main(String[] args)
      {
         Point point = new Point();
         point.x = 100;
         point.y = 200;

         // будет работать
         points = new ArrayList<Point>();
         points.add(point);
      }
   }
}
public class Solution
{
   private static ArrayList<Point> points;
}

class Point
{
   int x;
   int y;

   public static void main(String[] args)
   {
      Point point = new Point();
      point.x = 100;
      point.y = 200;

      // тут будет ошибка
      points = new ArrayList<Point>();
      points.add(point);
   }
}

Метод main в обычном классе Point не может обращаться к private static переменной points класса Solution!

Это, собственно, и есть главное отличие вложенного статического класса от обычного класса. Методы вложенного статического класса имеют доступ ко всем статическим переменным и методам своего класса родителя, даже если те объявлены private.

Ну а если разобраться, что тут удивительного? Модификатор private прямо говорит, что к переменным и методам, обозначенным этим модификатором, можно обращаться только изнутри их класса. Внутренний статический класс находится внутри класса-родителя? Да, тогда никаких проблем: обращайтесь сколько хотите.


undefined
12
Задача
Java Syntax Pro, 12 уровень, 4 лекция
Недоступна
Объекты внутренних и вложенных классов
В классе Outer есть внутренний (Inner) и вложенный (Nested) классы. В методе main класса Solution создай по одному объекту каждого из них.