CodeGym /Java Blog /무작위의 /익명 클래스
John Squirrels
레벨 41
San Francisco

익명 클래스

무작위의 그룹에 게시되었습니다
안녕! 오늘 수업에서는 중첩 클래스에 대한 주제를 계속 살펴보겠습니다. 이제 마지막 그룹인 익명의 내부 클래스를 위한 시간입니다. 다이어그램으로 돌아가 보겠습니다. 익명 클래스 - 2지난 수업에서 이야기한 로컬 클래스와 마찬가지로 익명 클래스도 일종의 내부 클래스입니다... 또한 몇 가지 유사점과 차이점이 있습니다. 그러나 먼저, 자세히 살펴보겠습니다. 왜 정확히 "익명"이라고 불립니까? 이에 답하기 위해 간단한 예를 살펴보겠습니다. 지속적으로 실행되고 무언가를 수행하는 기본 프로그램이 있다고 상상해 보십시오. 여러 모듈로 구성된 이 프로그램에 대한 모니터링 시스템을 만들고자 합니다. 하나의 모듈은 성능의 일반적인 지표를 추적하고 로그를 유지합니다. 두 번째는 오류 로그에 오류를 등록하고 기록합니다. 세 번째는 무단 액세스 시도 및 기타 보안 관련 사항과 같은 의심스러운 활동을 추적합니다. 본질적으로 세 모듈 모두 프로그램 시작 부분에서 시작하고 백그라운드에서 실행되어야 하므로,

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3개의 구체적인 클래스가 이를 구현합니다.

public class GeneralIndicatorMonitoringModule implements MonitoringSystem {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor security!");
   }
}
모든 것이 정상인 것 같습니다. 우리는 여러 모듈로 구성된 꽤 일관된 시스템을 가지고 있습니다. 그들 각각은 자신의 행동을 가지고 있습니다. 새 모듈이 필요한 경우 구현하기 쉬운 인터페이스가 있으므로 추가할 수 있습니다. 하지만 모니터링 시스템이 어떻게 작동할지 생각해 봅시다. 기본적으로 우리는 단지 3개의 객체( , , ) 익명 클래스 - 3를 생성 하고 각각에 대한 메서드를 호출하기 만 하면 됩니다. 즉, 우리가 해야 할 일은 3개의 객체를 생성하고 그들에 대해 1개의 메서드를 호출하는 것입니다. GeneralIndicatorMonitoringModuleErrorMonitoringModuleSecurityModulestartMonitoring()

public class Main {

   public static void main(String[] args) {

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

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

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
이렇게 작은 작업으로 우리는 전체 시스템을 작성했습니다: 3개의 클래스와 하나의 인터페이스! 그리고 이 모든 것은 6줄의 코드를 달성하기 위한 것입니다. 반면에 우리의 선택은 무엇입니까? 음, 우리가 이러한 "일회성" 클래스를 작성하는 것은 그리 멋진 일이 아닙니다. 하지만 이 문제를 어떻게 해결할 수 있습니까? 여기서 익명의 내부 클래스가 우리를 구해줍니다! 우리의 경우에는 다음과 같습니다.

public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor general indicators!");
           }
       };

       

MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor security!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
무슨 일이 일어나고 있는지 알아 봅시다! 인터페이스 개체를 만드는 것처럼 보입니다.

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
그러나 우리는 인터페이스 개체를 만들 수 없다는 것을 오랫동안 알고 있었습니다! 그리고 그것은 불가능합니다. 사실, 그것은 우리가 하는 일이 아닙니다. 우리가 쓸 때:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
다음은 Java 시스템 내에서 발생합니다.
  1. 인터페이스 를 구현하는 명명되지 않은 Java 클래스가 생성됩니다 MonitoringSystem.
  2. 컴파일러가 이러한 클래스를 발견하면 인터페이스의 모든 메서드를 구현해야 합니다 MonitoringSystem(이 작업을 3번 수행했습니다).
  3. 이 클래스의 하나의 객체가 생성됩니다. 코드에 주의하세요.

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
끝에 세미콜론이 있습니다! 이유가 있습니다. 우리는 동시에 클래스를 선언하고(중괄호 사용) 인스턴스를 생성합니다(사용 ();). 우리의 세 개체는 각각 startMonitoring()고유한 방식으로 메서드를 재정의합니다. 마지막으로 각각에 대해 이 메서드를 호출합니다.

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

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
그게 다야! 우리는 목표를 달성했습니다. 세 개의 개체를 만들고 MonitoringSystem세 가지 방법으로 메서드를 재정의하고 세 번 호출했습니다. 세 개의 모듈이 모두 성공적으로 호출되어 실행 중입니다. 동시에 프로그램의 구조가 훨씬 더 단순해졌습니다! 결국, GeneralIndicatorMonitoringModule, ErrorMonitoringModuleSecurityModule클래스는 이제 프로그램에서 완전히 제거될 수 있습니다! 우리는 그것들이 필요하지 않습니다. 그것들 없이도 훌륭하게 일했습니다. 각 익명 클래스에 다른 동작이 필요한 경우(예: 다른 클래스에는 없는 고유한 메서드) 쉽게 추가할 수 있습니다.

MonitoringSystem generalModule = new MonitoringSystem() {
  
   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
  
   public void someSpecificMethod() {

       System.out.println("Specific method only for the first module");
   }
};
Oracle 설명서는 "로컬 클래스를 한 번만 사용해야 하는 경우 [익명 클래스]를 사용하십시오."라는 좋은 권장 사항을 제공합니다. 익명 클래스는 본격적인 내부 클래스입니다. 따라서 정적 및 개인 변수를 포함하여 외부 클래스의 변수에 액세스할 수 있습니다.

public class Main {

   private static int currentErrorCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {
          
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }

           public int getCurrentErrorCount() {

               return currentErrorCount;
           }
       };
   }
}
로컬 클래스와 공통점이 있습니다. 즉, 선언된 메서드 내에서만 볼 수 있습니다. 위의 예에서 메서드 errorModule외부의 개체에 액세스하려는 모든 시도는 main()실패합니다. 그리고 익명 클래스가 "조상"(내부 클래스)에서 상속하는 또 다른 중요한 제한 사항이 있습니다. 익명 클래스는 정적 변수 및 메서드를 포함할 수 없습니다 . 위의 예에서 메서드를 getCurrentErrorCount()정적으로 만들려고 하면 컴파일러에서 오류가 발생합니다.

// Error! Inner classes cannot have static declarations
public static int getCurrentErrorCount() {

   return currentErrorCount;
}
정적 변수를 선언하려고 하면 동일한 결과를 얻습니다.

MonitoringSystem errorModule = new MonitoringSystem() {

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

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }

};
그리고 오늘 수업이 끝났습니다! 그러나 중첩된 클래스의 마지막 그룹을 조사했지만 아직 이 항목을 완료하지 못했습니다. 중첩 클래스에 대해 무엇을 더 배우게 될까요? 당신은 확실히 곧 알게 될 것입니다! :)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION