[JAVA] 중첩 선언과 익명 객체

dev_swanim·2023년 4월 10일

JAVA 문법

목록 보기
5/10
post-thumbnail

중첩 클래스란?

중첩 클래스(Nested Class) : 클래스 내부에 선언한 클래스

  • 클래스 멤버를 쉽게 사용할 수 있다
  • 외부에는 중첩 관계 클래스를 감춰 코드의 복잡성을 줄일 수 있다
  • 특정 클래스와의 관계만 존재할 경우, 중첩 클래스로 선언하는 게 유지보수에 도움된다

중첩 클래스 분류

  1. 멤버 클래스 : 클래스의 멤버로서 선언됨

    (1) 인스턴스 멤버 클래스 : A 객체를 생성해야 B 객체 생성 가능

    class A{
    	class B{}
    }

    (2) 정적 멤버 클래스 : A객체를 생성하지 않아도 B 객체 생성 가능

    class A{
    	static class B{}
    }
  2. 로컬 클래스 : 메소드 내부에서 선언됨

    • method가 실행할 때만 B 객체를 생성 가능
    class A{
    	void method(){
    		class B{}
    	}
    }

2. 인스턴스 멤버 클래스

구분접근 범위
public class B{ }다른 패키지에서 B 클래스를 사용
class B { }같은 패키지에서만 B 클래스를 사용
private class B { }A 클래스 내부에서만 B 클래스 사용
  • B 객체를 A 클래스 내부에서 선언하여 사용한다
    • 인스턴스 필드값, 생성자, 인스턴스 메소드에서 생성 가능
public class A{
	//인스턴스 멤버 클래스
	class B {}

	//인스턴스 필드 값으로 B 객체 대입
	B field = new B();

	//생성자
	A(){
		B b = new B();
	}
	//인스턴스 메소드
	void method(){
		B b = new B();
	}
}

//main
A a = new A(); // A 객체 생성

A.B b = a.new B(); // B 객체 생성

3. 정적 멤버 클래스

구분접근 범위
public static class B { }다른 패키지에서 B 클래스 사용
static class B { }같은 패키지에서만 B 클래스 사용
private static class B { }A 클래스 내부에서만 B 클래스 사용
public class A{
	// 인스턴스 멤버 클래스
	static class B {}

	// 인스턴스 필드 값으로 B 객체 대입
	B field1 = new B();

	// 정적 필드 값으로 B 객체 대입
	static B field2 = new B();

	// 생성자
	A(){
		B b = new B();
	}

	// 인스턴스 메소드
	void method1(){
		B b = new B();
	}

	// 정적 메소드
	static void method2(){
		B b = new B();
	}
}

//main

A.B b = new a.B(); // B 객체 생성
b.method1(); //b소속의 메소드가 있다면 이런 방식으로 사용

4. 로컬 클래스

  • 생성자나 메소드 내부에서 선언된 로컬 클래스
public class A{
	//생성자
	A(){
		//로컬 클래스 선언
		class B{}
		
		//로컬 객체 생성
		B b = new B();
	}

	//메소드
	void method(){
		//로컬 클래스 선언
		class B{}
	}
} 

5. 바깥 멤버 접근

  • 중첩 클래스는 바깥 클래스의 멤버(필드, 메소드)에 접근 가능 → 중첩 클래스가 속해있는 상위 클래스의 멤버 접근

바깥 클래스의 멤버 접근 제한

구분바깥 클래스의 사용 가능한 멤버
인스턴스 멤버 클래스바깥 클래스의 모든 필드와 메소드
정적 멤버 클래스바깥 클래스의 정적 필드와 정적 메소드
  • 정적 멤버 클래스는 바깥 객체가 없어도 사용 가능해야 하니 바깥 클래스의 인스턴스 필드와 메소드는 사용하지 못한다
public class A{
	//A의 인스턴스 필드와 메소드
	int field1;
	void method1(){}

	//A의 정적 필드와 메소드
	static int field2();
	static void method2() {}

	//인스턴스 멤버 클래스
	class B{
		void method(){
		//A의 인스턴스 필드와 메소드 사용
		field1 = 10;
		method1();

		//A의 정적 필드와 메소드 사용
		field2 = 10;
		method2();
		}
	} 

	//정적 멤버 클래스
	static class C{
		void method(){
			//A의 인스턴스 필드, 메소드 사용 불가
			
			//A의 정적 필드와 메소드 사용
			field2 = 10;
			method2();
		}
	}
}

바깥 클래스의 객체 접근

  • 중첩 클래스 내부에서 바깥 클래스의 객체를 얻기 위해서는 바깥 클래스 이름에 this를 붙여주면 된다
//바깥 클래스 이름.this -> 바깥 객체를 가리킴

public class A{
	...	
	class B{
		this.method(); // B객체의 필드와 메소드 사용(B 자신의 것을 접근할 때)
	
		A.this.method(); // A객체의 필드와 메소드 사용
	} 
}

6. 중첩 인터페이스

  • 인터페이스를 클래스 내부에 선언하는 이유는 해당 클래스와 긴밀한 관계를 갖는 구현 객체를 만들기 위함이다
    • 안드로이드 같은 UI 프로그램에서 이벤트를 처리할 목적으로 많이 활용
class A{
	[public | private] [static] interface B{
		// 상수필드
		// 추상 메소드
		// 디폴트 메소드
		// 정적 메소드 
	}
}

예제

public class Button{
	//정적 멤버 인터페이스
	public static interface ClickListener{
		//추상 메소드
		void onClick();
	}

	//필드
	private ClickListener clickListener;

	//메소드
	public void setClickListener(ClickListener clickListener){
		this.clickListener = clickListener;
	}

	public void click(){
		this.clickListener.onClick();
	}
}

public class ButtonExample{
	public static void main(String[] args){
		//OK 버튼 객체 생성
		Button btnOK = new Button();

		//OK 버튼 클릭 이벤트를 처리할 ClickListener 구현 클래스(로컬 클래스)
		class OkListener implements Button.ClickListener{
			@Override
			public void onClick(){
				System.out.println("Ok버튼을 클릭함");
			}
		}

		//Ok 버튼 객체에 ClickListener 구현 객체 넣기
		btnOk.setClickListener(new OkListener());

		//Ok 버튼 클릭
		btnOk.click();

		///////////////////////////////////////
		
		//Cancel 버튼 객체 생성
		Button btnCancel = new Button();
	
		//Cancel 버튼 클릭 이벤트를 처리할 ClickListener 구현 클래스(로컬 클래스)
		class CancelListener implements Button.ClickListener{
			@Override
			public void onClick(){
				System.out.println("Cancel 버튼 클릭");
			}
		}

		//Cancel 버튼 객체에 ClickListener 구현 객체 넣기
		btnCancel.setClickListener(new CancelListener());

		//Cancel 버튼 클릭
		btnCancel.click();
	}
}

7. 익명 객체

  • 이름이 없는 객체
  • 클래스를 선언하지 않기 때문에 쉽게 객체 생성
  • 필드값, 로컬 변수값, 매개변수값으로 사용됨

익명 자식 객체

  • 부모 클래스를 상속받아 생성되는 객체
//필드에 익명 자식 객체 대입
private Tire tire2 = new Tire(){
	@Override
	public void roll(){
		System.out.println("익명 자식 Tire 객체1이 굴러간다");
	};
};

//메소드(로컬변수이용)
public void run2(){
	//로컬 변수에 익명 자식 객체 대입
	Tire tire = new Tire(){
	@Override
	public void roll(){
		System.out.println("익명 자식 Tire 객체2가 굴러간다"); 
		}
	};
	tire.roll();
}

익명 구현 객체

  • 인터페이스를 구현해서 만드는 경우
  • 안드로이드 같은 UI 프로그램에서 이벤트 처리하는 객체로 많이 사용
public interface RemoteControl{
	//추상 메소드
	void turnOn();
	void turnOff();
}
public class Home{
	//필드에 익명 구현 객체 대입
	private RemoteControl rc = new RemoteControl(){
		@Override
		public void turnOn(){
			System.out.println("TV를 켭니다");
		}
	}
}

📚참고 문헌

이것이 자바다(신용권, 임경균 지음)

profile
데이터와 백엔드를 공부하고 있습니다😌

0개의 댓글