본문 바로가기

study/java

자바/JAVA 중첩 클래스, 중첩 인터페이스

중첩 클래스와 중첩 인터페이스(Nested class, Nested interface): 클래스 내에 클래스와 인터페이스를 선언할 수 있다.

 

중첩 클래스: 클래스 내부에 선언한 클래스. 바깥 클래스가 없다면 필요 없을 만큼 긴밀한 관계일 때 사용한다.

중첩 인터페이스: 클래스 내부에 선언한 인터페이스. 바깥 클래스가 없다면 필요 없을 만큼 긴밀한 관계일 때 사용한다.

 

중첩 클래스에는 크게 멤버 클래스와 로컬 클래스로 나눌 수 있다.

 

 멤버 클래스는 클래스의 멤버, 즉 필드와 메소드로 선언된 클래스이고, 인스턴스 멤버 클래스와 정적 멤버 클래스로 나눌 수 있다. 로컬 클래스는 생성자 또는 메소드 내부에 선언된 클래스이다.

 

 중첩 클래스도 컴파일하면 파일이 생기는데 멤버 클래스는 "A % B.class" 의 형태로, A 부분에는 바깥 클래스의 이름이, B 부분에는 중첩 클래스의 이름이 들어있다. 로컬 클래스는 "A $1 B.class"로 클래스 이름 부분은 같으나 $ 옆에 숫자가 붙어 로컬 클래스의 식별 변호 역할을 한다.

 

 인스턴스 멤버 클래스는 인스턴스 필드와 메소드만 선언이 가능하다. 인스턴스 멤버 클래스가 생성되려면 바깥 클래스에서 객체를 생성해야 하므로, 객체 없이 사용할 수 있는 static, 정적 필드와 메소드는 선언할 수 없다.

 

public class A {
	class B {
    	int field1;
        static int field2;// 컴파일 에러 발생
    }
}
//인스턴스 멤버 클래스 객체 생성.
A a = new A();
A.B b = a.new B();

 

반대로, 정적 멤버 클래스는 static으로 선언되므로, 인스턴스 멤버, 정적 멤버 다 선언할 수 있다.

 

 

로컬 클래스는 접근제한자, static 을 붙일 수 없다. -> 메소드, 생성자 블록에서만 사용해서

또한 인스턴스 필드, 메소드만 선언 가능하다. -> static을 못붙임, 인스턴스 멤버 클래스가 못하는 이유와 같음.

 

 

 인스턴스 멤버 클래스는 바깥 클래스의 정적 필드로 선언될 수 없다. 그러나 정적 멤버 클래스는 바깥 클래스의 정적 필드로 선언될 수 있다. 또한 바깥 정적 메소드에서도 인스턴스 멤버 클래스는 사용할 수 없지만, 정적 멤버 클래스는 사용할 수 있다.

publi class A{
	class B{}
    static class C{}
    
    static B b = new B(); // 컴파일 에러
    static C c =  new C();// 잘 됨.
    
    static void method(){
    	B b = new B();//컴파일 에러
        C c = new C();//잘 됨.
}

 static 이라는 키워드가 붙으면 객체 생성 없이도 사용할 수 있어야 하지만, 인스턴스 멤버 클래스는 객체를 생성해야 사용할 수 있기 때문에 위와 같은 결과가 나온다.

 

 인스턴스 멤버 클래스는 바깥 클래스의 필드와 메소드를 static 키워드와 상관없이 사용할 수 있다. 그러나 정적 멤버 클래스는 바깥 클래스의 인스턴스 멤버를 사용할 수 없다.(정적 필드, 메소드는 사용할 수 있다.)

 

 로컬 클래스가 메소드, 생성자의 매개변수나 로컬 변수를 사용하려면 그 매개 변수와 로컬 변수는 final 특징을 가져야 한다. 따라서 로컬 클래스가 사용하는 매개변수, 로컬 변수는 변경될 수 없다. java8 이후론 명시하지 않아도 자동으로 붙여진다.

public void method1(int arg) {
		int localVariable = 1;
		// arg = 100; 수정 안됨.
		// localVariable = 100; 수정 안됨. 컴파일 에러
		
		class Inner{
			void method() {
				int result = arg + localVariable;
			}
		}
	}

 

바깥 클래스의 필드, 메소드를 접근할 때, this 키워드를 이용해 접근할 수도 있다.

ex) 바깥클래스.this.필드 또는 메소드 

 

 

중첩 인터페이스: 클래스의 멤버로 선언된 인터페이스. staic을 붙일 수도 있고, 안붙여도 된다. 필드의 다형성을 이용할 있어 보통 이벤트를 처리하는 UI, 버튼 같은 경우에 사용한다.

public class Button {
	OnClickListener listener;
	
	void setListener(OnClickListener listener) {
		this.listener = listener;
	}
	
	void click() {
		listener.onClick();
	}
	
	static interface OnClickListener{
		void onClick();
	}
}