본문 바로가기

프로그래밍 언어 (プログラミング言語)/JAVA

Anonymous class in JAVA

익명 클래스 라고도 부른며, C++에서의 임시 객체와 같은 개념이다. 

package Anonymous;

public class Insect {

	void attack(){
		System.out.println("곤충은 공격을 한다");
	}
}

 

package Anonymous;

public class Anonymous {

	//★★방법 1 : 필드에 익명자식 객체를 생성 
	Insect spider1 = new Insect(){
		
		String name = "무당거미";
		//거미줄을 치다.
		void cobweb(){
			System.out.println("사각형으로 거미줄을 친다.");
		}
		
		@Override
		void attack() {
			System.out.println(name + " 독을 발사한다.");
		}
	};
	
	//★★방법2 : 로컬변수의 초기값으로 대입
	void method1(){
		Insect spider2 = new Insect(){
			
			String name = "늑대거미";
			//거미줄을 치다.
			void cobweb(){
				System.out.println("육각형으로 거미줄을 친다.");
			}
			
			@Override
			void attack() {
				System.out.println(name + " 앞니로 문다.");
			}
		};
		
		//로컬변수이기 때문에 메서드에서 바로 사용
		spider2.attack();
	}
	
	//★★방법3 : 익명객체 매개변수로 대입
	void method2(Insect spider){
		spider.attack();
	}

 

package Anonymous;

public class AnonymousExample {

	public static void main(String[] args) {
		
		Anonymous a = new Anonymous();
		
		//방법 1 : 익명객체 필드 사용
		a.spider1.attack();

		//방법2 : 익명객체 로컬 변수 사용
		a.method1();
		
		//방법3 : 매개변수로 익명개체 사용
		a.method2(new Insect(){
			String name = "타란툴라";
			
			//거미줄을 치다.
			void cobweb(){
				System.out.println("그냥 마구잡이로 친다.");
			}
			
			@Override
			void attack() {
				System.out.println(name + " 공격 안하고 후퇴한다..");
			};
		});
		
		//익명객체 내부에서 새롭게 정의된 필드,메서드는 부모객체로 생성된 spider1에서 접근할 수 없음!!!
		a.spider1.name = "왕거미"; //익명객체에서 새롭게 정의된 필드 (접근불가)
		a.spider1.cobweb(); //익명객체에서 새롭게 정의된 메서드 (접근불가)
		a.spider1.attack(); //부모클래스 Insect에서 오버라이딩해서 재정의한 메서드 (접근가능)
	}

}

 

극단적인 예시를 들어보겠습니다.

웃긴 예시긴 한데 ㅋㅋ

곤충이라는 부모클래스를 상속받는 거미라는 구현클래스가 있다.

근데...세상을 보아하니 거미는 "전 세계에 약 3만 종이 알려져 있으며 한국에는 약 600종이 분포한다."

암튼, 이 거미의 공통적인 특징도 없고, 잠깐 프로그램 로직에서 단발성(단 한번)으로 등장해서 거미줄을 각자

의 방식으로 치고 영원히 사라진다고 칩시다.

 

그러면 여러분은 3만종에 대한 거미 클래스를 만들고 있을 것인지,  코드에서 일시적으로 정의하

여 쓰고 버릴지...생각해보시면 됩니다.  

 

한번만 사용될 목적인데 3만개의 클래스를 별도로 만들어줘야하고;;;, 코드에서도 객체를 생성해야한다.???

-> 생각만해도 귀찮고 무의미, 유지보수에 불리함

 

클래스를 별도로 만들 필요없이 코드에서 익명객체를 생성/정의하여 단 한번의 쓰임을 다하고 소멸한다.

-> 덜 귀찮고 합리적임, 유지보수에 유리함

 

답이 나왔을거라고 생각됩니다.

 

 

익명객체(익명클래스) 컴파일시 만들어지는 $ 클래스

 

다들 아시겠지만, 코딩된 .java 파일은 자바 컴파일러를 통해 컴파일되고 .class 파일을 떨구게 됩니다.

보통 .java 파일이 .class 파일과 1:1관계를 맺지만 익명객체(익명클래스)가 사용된 .java 파일을 컴파일 하게

되면 .class 파일 뿐만 아니라 $.class를 떨구게 됩니다.

만약 A.java라는 파일에서 익명객체를 정의했다면 A.class, [A$1.class] 이렇게 2개 클래스 파일이 생깁니다.

만약 익명객체를 2개 A.java 파일에 정의했다면 A.class,[ A$1.class, A$2.class ] 이렇게 3개 클래스 파일이 생깁니다.

 

규칙은 자바파일명${익명객체정의된순번}.class 으로 생각하시면 됩니다.

 

실제로 이렇게 클래스 파일이 생성되었는지 확인해보겠습니다.

프로젝트 우클릭 -> Properties -> Java Build Path -> Source 항목 -> 하단 경로..

 

프로젝트 우클릭

프로젝트 class 떨구는 경로 확인 (Defalut output folder)

JAVA_STUDY/bin/Anonymous 내 $ class파일 확인

 

내용을 보시면, Anonymous 클래스에서 익명객체 정의를 2번하였기 때문에  

Anonymous$1.class,  Anonymous$2.class 확인됩니다. 

또 AnonymousExample 예제에서 메서드 매개변수로 넘겨줄때 익명객체를 1번 정의하였으니

AnonymousExample$1.class가 있는게 확인됩니다.