JavaRush /Java Blog /Random-KO /Java의 익명 클래스

Java의 익명 클래스

Random-KO 그룹에 게시되었습니다
안녕하세요! 오늘 수업에서는 중첩 클래스에 대한 주제를 계속해서 살펴보겠습니다. 마지막 그룹인 Java의 익명 내부 클래스 차례입니다. 다이어그램으로 돌아가 보겠습니다. 익명 클래스 - 2지난 강의에서 이야기한 로컬 클래스와 마찬가지로 익명 클래스는 내부 클래스의 하위 집합입니다. 그들은 또한 그들 사이에 몇 가지 유사점과 차이점을 가지고 있습니다. 하지만 먼저 알아봅시다. 왜 실제로 "익명"이라고 불리는 걸까요? 이를 위해 간단한 예를 살펴보겠습니다. 끊임없이 실행되고 무언가를 수행하는 메인 프로그램이 있다고 상상해 보세요. 우리는 여러 모듈로 구성된 이 프로그램에 대한 모니터링 시스템을 만들고 싶습니다. 한 모듈은 일반 성능 지표를 모니터링하고 로그를 유지하며, 두 번째 모듈은 오류 로그에 오류를 기록 및 기록하고, 세 번째 모듈은 의심스러운 활동(예: 무단 액세스 시도 및 기타 보안 관련 사항)을 모니터링합니다. 세 가지 모듈 모두 기본적으로 프로그램 시작 부분에서 시작하여 백그라운드에서 실행되어야 하므로 공통 인터페이스를 만드는 것이 좋습니다.
public interface MonitoringSystem {

   public void startMonitoring();
}
이는 3개의 특정 클래스로 구현됩니다.
public class GeneralIndicatorsMonitoringModule implements MonitoringSystem {

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Bug Tracking Monitoring Started!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Security monitoring started!");
   }
}
모든 것이 정상인 것 같습니다. 우리는 여러 모듈로 구성된 상당히 명확한 시스템을 보유하고 있습니다. 그들 각각은 고유한 행동을 가지고 있습니다. 새 모듈이 필요하면 추가할 수 있습니다. 구현하기 매우 쉬운 인터페이스가 있기 때문입니다. 하지만 우리의 모니터링 시스템이 어떻게 작동할지 생각해 봅시다. 기본적으로 , , - 익명 클래스 - 33개의 개체를 만들고 각 개체에 대해 메서드 를 호출하면 됩니다. 즉, 3개의 개체를 만들고 해당 개체에 대해 1개의 메서드를 호출하기만 하면 됩니다. GeneralIndicatorsMonitoringModuleErrorMonitoringModuleSecurityModulestartMonitoring()
public class Main {

   public static void main(String[] args) {

       GeneralIndicatorsMonitoringModule generalModule = new GeneralIndicatorsMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
콘솔 출력:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
그리고 이렇게 작은 작업을 위해 우리는 3개의 클래스와 1개의 인터페이스로 전체 시스템을 작성했습니다! 그리고 이 모든 것은 6줄의 코드를 위한 것입니다. 반면에 우리의 선택은 무엇입니까? 예, 우리가 그런 "일회용" 클래스를 작성했다는 것은 별로 멋지지 않습니다. 하지만 어떻게 이 문제를 해결할 수 있을까요? 익명의 내부 클래스가 우리를 도와주는 곳입니다 ! 우리의 경우에는 다음과 같습니다.
public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Monitoring of general indicators has started!");
           }
       };



           MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Bug Tracking Monitoring Started!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Security monitoring started!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
여기서 무슨 일이 일어나고 있는지 알아봅시다! 인터페이스 객체를 생성하는 것처럼 보입니다.
MonitoringSystem generalModule = new MonitoringSystem() {

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
};
그러나 우리는 인터페이스 객체를 생성하는 것이 불가능하다는 것을 오랫동안 알고 있었습니다! 그렇죠, 불가능해요. 사실 우리는 그렇게 하지 않습니다. 우리가 쓰는 순간:
MonitoringSystem generalModule = new MonitoringSystem() {

};
Java 시스템 내부에서는 다음이 발생합니다.
  1. 을 구현하는 이름 없는 Java 클래스가 생성됩니다 MonitoringSystem.
  2. 이러한 클래스를 보는 컴파일러는 모든 인터페이스 메서드를 구현하도록 요구합니다 MonitoringSystem(우리는 이 작업을 3번 수행했습니다).
  3. 이 클래스의 객체 하나가 생성됩니다. 코드에 주의하세요:
MonitoringSystem generalModule = new MonitoringSystem() {

};
마지막에 세미콜론이 있어요! 그녀가 거기 서 있는 데에는 이유가 있습니다. 동시에 클래스를 선언하고(중괄호를 통해) 해당 객체를 생성합니다. (); 세 객체 각각은 startMonitoring()고유한 방식으로 메서드를 재정의했습니다. 결국 우리는 각각에 대해 이 메서드를 간단히 호출합니다.
generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
콘솔 출력:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
그게 다야! 우리는 작업을 완료했습니다. 세 개의 객체를 생성하고 MonitoringSystem이를 세 가지 다른 방식으로 재정의하고 세 번 호출했습니다. 세 가지 모듈이 모두 성공적으로 시작되어 작동합니다. 동시에, 우리 프로그램의 구조는 훨씬 더 단순해졌습니다! GeneralIndicatorsMonitoringModule결국 , ErrorMonitoringModule이제 수업을 SecurityModule프로그램에서 완전히 제거할 수 있습니다! 우리는 그것들이 필요하지 않습니다. 그것들 없이도 우리는 잘 관리했습니다. 각 익명 모듈 클래스에 다른 동작, 다른 클래스에는 없는 고유한 특정 메서드가 필요한 경우 쉽게 추가할 수 있습니다.
MonitoringSystem generalModule = new MonitoringSystem() {

   @Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }

   public void someSpecificMethod() {

       System.out.println("Specific method for first module only");
   }
};
Oracle 문서에는 "일회용 로컬 클래스가 필요한 경우 익명 클래스를 사용하십시오."라는 좋은 권장 사항이 있습니다. 익명 클래스는 본격적인 내부 클래스입니다. 따라서 정적 및 비공개 변수를 포함한 외부 클래스 변수에 액세스할 수 있습니다.
public class Main {

   private static int currentErrorsCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {

           @Override
           public void startMonitoring() {
               System.out.println("Bug Tracking Monitoring Started!");
           }

           public int getCurrentErrorsCount() {

               return currentErrorsCount;
           }
       };
   }
}
로컬 클래스와 공통점이 있습니다. 즉, 정의된 메서드 내에서만 표시됩니다. 위의 예에서는 errorModule메서드 외부에서 개체에 액세스하려는 모든 시도가 main()실패합니다. 그리고 익명 클래스가 "조상"으로부터 상속받은 또 하나의 중요한 제한 사항은 내부 클래스입니다. 익명 클래스는 정적 변수와 메서드를 포함할 수 없습니다 . 위 예제의 메서드를 정적으로 만들려고 하면 getCurrentErrorsCount()컴파일러에서 오류가 발생합니다.
//error! Inner classes cannot have static declarations
public static int getCurrentErrorsCount() {

   return currentErrorsCount;
}
정적 변수를 선언하려고 하면 동일한 결과를 얻습니다.
MonitoringSystem errorModule = new MonitoringSystem() {

   //error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Bug Tracking Monitoring Started!");
   }

};
마지막으로, 이 주제가 최대한 간단하고 명확하게 설명되어 있는 익명 수업 주제에 관한 훌륭한 동영상을 추천해 드릴 수 있습니다. :)
그리고 오늘 우리 수업은 끝났습니다! 중첩 클래스의 마지막 그룹을 다루었지만 아직 이 주제가 끝나지 않았습니다. 중첩 클래스에 관해 다음에는 무엇을 공부할까요? 당신은 곧 알게 될 것입니다! :)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION