Java - внутренние классы

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

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

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

Syntax

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

class Outer_Demo {
   class Inner_Demo {
   }
}

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

  • Non-static nested classes - Это нестатические члены класса.

  • Static nested classes - Это статические члены класса.

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

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

Внутренние классы бывают трех типов в зависимости от того, как и где вы их определяете. Они -

  • Внутренний класс
  • Локальный для метода внутренний класс
  • Анонимный внутренний класс

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

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

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

Example

class Outer_Demo {
   int num;
   
   // inner class
   private class Inner_Demo {
      public void print() {
         System.out.println("This is an inner class");
      }
   }
   
   // Accessing he inner class from the method within
   void display_Inner() {
      Inner_Demo inner = new Inner_Demo();
      inner.print();
   }
}
   
public class My_class {

   public static void main(String args[]) {
      // Instantiating the outer class 
      Outer_Demo outer = new Outer_Demo();
      
      // Accessing the display_Inner() method.
      outer.display_Inner();
   }
}

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

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

Output

This is an inner class.

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

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

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

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

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

Example

class Outer_Demo {
   // private variable of the outer class
   private int num = 175;  
   
   // inner class
   public class Inner_Demo {
      public int getNum() {
         System.out.println("This is the getnum method of the inner class");
         return num;
      }
   }
}

public class My_class2 {

   public static void main(String args[]) {
      // Instantiating the outer class
      Outer_Demo outer = new Outer_Demo();
      
      // Instantiating the inner class
      Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();
      System.out.println(inner.getNum());
   }
}

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

Output

This is the getnum method of the inner class: 175

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

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

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

Example

public class Outerclass {
   // instance method of the outer class 
   void my_Method() {
      int num = 23;

      // method-local inner class
      class MethodInner_Demo {
         public void print() {
            System.out.println("This is method inner class "+num);	   
         }   
      } // end of inner class
	   
      // Accessing the inner class
      MethodInner_Demo inner = new MethodInner_Demo();
      inner.print();
   }
   
   public static void main(String args[]) {
      Outerclass outer = new Outerclass();
      outer.my_Method();	   	   
   }
}

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

Output

This is method inner class 23

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

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

Syntax

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

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

Example

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("This is an example of anonymous inner class");
         }
      };
      inner.mymethod();	
   }
}

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

Output

This is an example of anonymous inner class

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

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

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

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

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

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

Example

// interface
interface Message {
   String greet();
}

public class My_class {
   // method which accepts the object of interface Message
   public void displayMessage(Message m) {
      System.out.println(m.greet() +
         ", This is an example of anonymous inner class as an argument");  
   }

   public static void main(String args[]) {
      // Instantiating the class
      My_class obj = new My_class();

      // Passing an anonymous inner class as an argument
      obj.displayMessage(new Message() {
         public String greet() {
            return "Hello";
         }
      });
   }
}

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

Output

Hello, This is an example of anonymous inner class as an argument

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

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

Syntax

class MyOuter {
   static class Nested_Demo {
   }
}

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

Example

public class Outer {
   static class Nested_Demo {
      public void my_method() {
         System.out.println("This is my nested class");
      }
   }
   
   public static void main(String args[]) {
      Outer.Nested_Demo nested = new Outer.Nested_Demo();	 
      nested.my_method();
   }
}

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

Output

This is my nested class