В этой главе мы обсудим внутренние классы Java.

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

В Java, подобно методам, переменные класса тоже могут иметь в качестве своего члена другой класс. В Java допускается написание класса внутри другого. Класс, написанный внутри, называется в Java вложенным классом, а класс, который содержит внутренний класс, называется внешним классом.

Синтаксис

Ниже приведен синтаксис для записи вложенного класса. Здесь класс Outer_Demo – это внешний класс, а класс Inner_Demo – вложенный класс.

class Outer_Demo {
   class Nested_Demo {
   }
}

Вложенные классы в Java делятся на два типа:

  • Нестатические вложенные классы – нестатические члены класса.
  • Статические вложенные классы – статические члены класса.
Типы вложенных классов, структура вложенных классов

Внутренние классы (нестатические вложенные классы)

Внутренние классы – это механизм безопасности в Java. Мы уже знаем, что класс не может быть связан с модификатором доступа private, но если у нас есть класс как член другого класса, то внутренний класс может быть private. И это также используется для доступа к закрытым (private) членам класса.

В Java внутренние классы имеют три типа в зависимости от того, как и где Вы их определяете:

  • внутренний класс;
  • локальный метод внутреннего класса;
  • анонимный внутренний класс.

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

Создать внутренний класс в Java довольно просто. Вам просто нужно написать класс внутри класса. В отличие от класса, внутренний класс может быть закрытым (private), и после того, как Вы объявляете внутренний класс закрытым, он не может быть доступен из объекта вне класса.

Ниже приведен пример создания внутреннего класса и получения доступа к нему. В данном примере мы делаем внутренний класс private и получаем доступ к классу с помощью метода.

Пример

class Outer_Demo {
   int num;
   
   // Внутренний класс
   private class Inner_Demo {
      public void print() {
         System.out.println("Это внутренний класс");
      }
   }
   
   // Доступ к внутреннему классу из метода
   void display_Inner() {
      Inner_Demo inner = new Inner_Demo();
      inner.print();
   }
}
   
public class My_class {

   public static void main(String args[]) {
      // Создание внешнего класса
      Outer_Demo outer = new Outer_Demo();
      
      // Доступ к методу display_Inner()
      outer.display_Inner();
   }
}

Здесь Вы можете заметить, что Outer_Demo – внешний класс, Inner_Demo – внутренний класс, display_Inner() – метод, внутри которого мы создаем внутренний класс, и этот метод вызывается из основного метода.

Если Вы скомпилируете и выполните вышеуказанную программу, Вы получите следующий результат:

Это внутренний класс

Доступ к частным (private) членам

Как упоминалось ранее, внутренние классы также используются в Java для доступа к закрытым членам класса. Предположим, у класса есть private члены. Для доступа к ним напишите в нем внутренний класс, верните частные члены из метода внутри внутреннего класса, скажем, методом getValue() и, наконец, из другого класса (из которого Вы хотите получить доступ к закрытым членам) вызовите метод getValue() внутреннего класса.

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

Outer_Demo outer = new Outer_Demo();
Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();

Следующий пример показывает, как получить доступ к закрытым членам класса с использованием внутреннего класса.

Пример

class Outer_Demo {
   // Частная переменная внешнего класса
   private int num = 2018;  
   
   // Внутренний класс
   public class Inner_Demo {
      public int getNum() {
         System.out.println("Это метод getnum внутреннего класса");
         return num;
      }
   }
}

public class My_class2 {

   public static void main(String args[]) {
      // Создание внешнего класса
      Outer_Demo outer = new Outer_Demo();
      
      // Создание внутреннего класса
      Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();
      System.out.println(inner.getNum());
   }
}

Если Вы скомпилируете и выполняете вышеуказанную программу, то получите следующий результат:

Это метод getnum внутреннего класса
2018

Локальный метод внутреннего класса

В Java мы можем написать класс внутри метода, и это будет локальный тип. Как и локальные переменные, возможности внутреннего класса ограничены в рамках метода.

Локальный метод внутреннего класса может быть создан только внутри метода, где определяется внутренний класс. Следующая программа показывает, как использовать локальный внутренний метод.

Пример

public class Outerclass {
   // Метод экземпляра внешнего класса
   void my_Method() {
      int num = 888;

      // Локальный метод внутреннего класса
      class MethodInner_Demo {
         public void print() {
            System.out.println("Это метод внутреннего класса: " + num);	   
         }   
      } // Конец внутреннего класса
	   
      // Доступ к внутреннему классу
      MethodInner_Demo inner = new MethodInner_Demo();
      inner.print();
   }
   
   public static void main(String args[]) {
      Outerclass outer = new Outerclass();
      outer.my_Method();	   	   
   }
}

Получим следующий результат:

Это метод внутреннего класса: 888

Анонимные внутренние классы в Java

Анонимный внутренний класс – это внутренний класс, объявленный без имени класса. В случае анонимных внутренних классов в Java мы объявляем и создаем их в одно и то же время. Как правило, они используются всякий раз, когда Вам необходимо переопределить метод класса или интерфейса. Синтаксис анонимного внутреннего класса в Java выглядит следующим образом:

Синтаксис

AnonymousInner an_inner = new AnonymousInner() {
   public void my_method() {
      ........
      ........
   }   
};

Пример

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

abstract class AnonymousInner {
   public abstract void mymethod();
}

public class Outer_class {

   public static void main(String args[]) {
      AnonymousInner inner = new AnonymousInner() {
         public void mymethod() {
            System.out.println("Это пример анонимного внутреннего класса");
         }
      };
      inner.mymethod();	
   }
}

Получим следующий результат:

Это пример анонимного внутреннего класса

Точно так же Вы можете переопределить методы конкретного класса, а также интерфейс, используя в Java анонимный внутренний класс.

Анонимный внутренний класс как аргумент

Как правило, если метод принимает объект интерфейса, абстрактный класс или конкретный класс, то мы можем реализовать интерфейс, расширить абстрактный класс и передать объект методу. Если это класс, мы можем напрямую передать его методу.

Но во всех трех случаях Вы можете в Java передать анонимный внутренний класс методу. Синтаксис передачи анонимного внутреннего класса в качестве аргумента метода:

Синтаксис

obj.my_Method(new My_Class() {
   public void Do() {
      .....
      .....
   }
});

Пример

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

// Интерфейс
interface Message {
   String greet();
}

public class My_class {
   // Метод, который принимает объект интерфейса Message
   public void displayMessage(Message m) {
      System.out.println(m.greet() +
         ", это пример анонимного внутреннего класса в качестве аргумента");  
   }

   public static void main(String args[]) {
      // Создание класса
      My_class obj = new My_class();

      // Передача анонимного внутреннего класса в качестве аргумента
      obj.displayMessage(new Message() {
         public String greet() {
            return "Привет";
         }
      });
   }
}

Если Вы скомпилируете и выполните вышеуказанную программу, то получите следующий результат:

Привет, это пример анонимного внутреннего класса в качестве аргумента

Статический вложенный класс в Java

Статический внутренний класс – это вложенный класс, который является статическим членом внешнего класса. Доступ к нему возможен без создания экземпляра внешнего класса с использованием других статических элементов. Как и статические члены, статический вложенный класс не имеет доступа к переменным экземпляра и методам внешнего класса. Синтаксис статического вложенного класса в Java выглядит следующим образом:

Синтаксис

class MyOuter {
   static class Nested_Demo {
   }
}

Пример

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

public class Outer {
   static class Nested_Demo {
      public void my_method() {
         System.out.println("Это мой вложенный класс");
      }
   }
   
   public static void main(String args[]) {
      Outer.Nested_Demo nested = new Outer.Nested_Demo();	 
      nested.my_method();
   }
}

Получим следующий результат:

Это мой вложенный класс

Оглавление