Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags more
Archives
Today
Total
관리 메뉴

ultra_dev

이것이 자바다 CH 9(중첩 선언과 익명 객체) 본문

이것이 자바다

이것이 자바다 CH 9(중첩 선언과 익명 객체)

ultra_dev 2023. 1. 13. 02:23

CH9

☑️ 중첩 클래스

: 클래스 내부에선언한 클래스

→ 외부에 중첩 관계 클래스를 감춤으로써 코드의 복잡성 줄일 수 있음

  • 클래스가 특정 클래스랑만 관계를 맺을 경우 편의성 때문에 중첩 클래스로 선언해서 사용하는 경우 많음

📌**멤버 클래스 : 클래스의 멤버로서 선언 되는 중첩 클래스**

  • 인스턴스 멤버 클래스
class A {
	class B {...}
}
-> A객체를 생성해야만 B객체 생성 가능
  • 정적 멤버 클래스
class A {
	static class B{...}
}
-> A 객체를 생성하지 않아도 B객체를 생성 가능

📌**로컬클래스 : 메소드 내부에서 선언되는 중첩 클래스**

class A {
	void method() {
		class B {...}
	}
}
-> 메소드 실행할 때만 B 객체 생성 가능

☑️ 중첩 클래스도 클래스이므로 컴파일시 .class 바이트코드 파일 생성

바깥클래스 $ 멤버클래스.class 
바깥클래스 $1 로컬클래스.class

☑️인스턴스 멤버 클래스

[public] class A{
	[public | private] class B{}
}

A클래스의 멤버로 선언되 B클래스 같은 경우를 말함
  • public class B{} : 다른 패키지에서 B클래스 사용 가능
  • class B {} : 같은 패키지에서만 B 클래스 사용 가능
  • private class B {} : A 클래스 내부에서만 B클래스 사용 가능

→ 이 경우 주로 A클래스 내부에서 사용되므로 private 접근제한을 갖는 것이 일반적

→ B클래스는 A 클래스 내부 인스턴스 필드값, 생성자, 메소드에서 생성 가능..

어디서나 생성 가능한 것이 아님 

why? A객체가 있어야 B객체도 생성할 수 있기 때문

public class A{
	class B{}
//필드값에 B 객체 대입
B field = new B();
//생성자
A() {
	B b = new B();
}
//메소드
void method() {
	B b = new B();
	}
}

📌 만약 B객체를 A클래스 외부에서 생성하려면 public,default 접근 제한을 가져야 하고

A객체 먼저 생성 후 B객체 생성

A a = new A();
A.B b = a.new B();
  • 인스턴스 멤버 클래스 B 내부에는 당연히 일반 클래스처럼 필드, 생성자, 메소드 선언 가능

but 정적필드와 정적메소드는 JAVA 17부터 선언 가능!

☑️ 정적 멤버 클래스

:static 키워드와 함께 A클래스의 멤버로 선언된 B 클래스

[public] class A {
	[public|private] static class B {}
}
  • publiac static class B {} : 다른 패키지에서 B클래스 사용 가능
  • static class B {} : 같은 패키지에서만 B클래스 사용 가능
  • private static class B {} : A 클래스 내부에서만 B 클래스 사용 가능

→ 정적 멤버 클래스 B는 A클래스 외부에서 사용하는 경우 많기 때문에 주로 default,public 접근 제한 가짐

  • A클래스 외부에서 B 객체 생성하려면 A 객체 생성 없이 A클래스로 접근해서 B 객체 생성 가능
A.B b = new A.B(); <ㅡ a객체 생성 필요없음

☑️ 로컬 클래스

: 생성자 또는 메소드 내부에서 다음과 같이 선언된 클래스

class A{
//생성자
 public A(){
	class B {}
}

//메소드
public void method(){
	class B{}
	}
}

→ 로컬 클래스는 생성자와 메소드가 실행될 동안에만 객체 생성 가능

→ 로컬 클래스 B 내부에는 일반 클래스처럼 필드,생성자,메소드 선언 올 수 있음

정적필드, 정적 메소드는 Java17부터 선언 가능

📌 로컬 변수(생성자 또는 메소드의 매개변수 또는 내부에서 선언된 변수)를 로컬 클래스에서 사용할 경우 로컬 변수는 final 특성을 갖게 되므로 값을 읽을 수만 있고 수정 불가

→ 로컬 클래스 내부에서 값을 변경하지 못하도록 제한

→ Java8 이후부터는 명시적으로 final 키워드 붙히지 않아도 되지만, 로컬 변수에 final 키워드 추가해서 명확히 하는 것도 좋음

public class A {

	public void method1(int arg) {
		//로컬 변수
		int var = 1;
//로컬 클래스
	class B {
		void method2() {
			
			System.out.println(arg);
			System.out.println(var);
		
//로컬 변수 수정 -> 불가능
		arg = 2; -> 불가능
		var = 2; -> 불가능
	}
}
//로컬 객체
B b = new B();

//로컬 객체 메소드 호출
b.method2();

//로컬변수 수정 -> 불가능
arg=3; -> 불가능
var=3; -> 불가
	}
}

☑️ 바깥 멤버 접근

:중첩 클래스는 바깥 클래스 멤버(필드,메소드)에 접근 가능

  • 인스턴스 멤버 클래스 : 바깥 클래스의 모든 필드와 메소드 사용 가능
  • 정적 멤버 클래스 : 바깥 클래스의 정적 필드와 정적 메소드 사용 가능

→ 정적 멤버 클래스는 바깥 객체가 없어도 사용 가능해야 하니 바깥 클래스의 인스턴스 필드와 인스턴스 메소드는 사용 불가

☑️바깥 클래스의 객체 접근

:중첩 클래스 내부에서 this는 해당 중첩 클래스 객체 의미하므로,

중첩 클래스 내부에서 바깥 클래스 객체 얻으려면 밑에처럼 해줘야 함

바깥클래스이름.this -> 바깥 객체 의미
public class A {

String field = "A";
void method(){..."A"}

	class B {
		String field = "B";
		void method(){..."B"}

		void abmethod(){
		System.out.println(this.field);//B클래스 필드
		this.method(); //B클래스의 메소드
		System.out.println(A.this.field);//A클래스 필드
		A.this.method(); // A클래스의 메소드

☑️ 중첩인터페이스

:클래스의 멤버로 선언된 인터페이스

→ 해당 클래스와 긴밀한 관계를 맺는 구현 객체 만들기 위해 사용

class A {
[public|private] [static] interface B {
//상수필드
//추상 메소드
//디폴트 메소드
//정적 메드
}

→ 외부의 접근 허용하려면 public, A클래스 내부에서만 사용할거면 private, 아무것도 안붙히면 같은 패키지 안에서만 접근 가능

→ 중첩 인터페이스는 안드로이드와 같은 UI 프로그램에서 이벤트 처리 목적으로 많이 활용됨

ex) 버튼 클릭했을 때 이벤트를 처리할 객체는 중첩인터페이스를 구현해서 만듦

☑️ 익명 객체 -> 보통 재사용 안할 경우 사용? 따로 빼서 인터페이스나 클래스하기도 낭비라고 생각되는?

: 이름이 없는 객체

  • 명시적으로 클래스를 선언하지 않아서 객체 쉽게 생성 가능
  • 익명 객체는 필드값, 로컬 변수값, 매개변수값으로 주로 사용됨
  • 클래스를 상속하거나 인터페이스를구현해야만 생성 가능
    • 클래스 상속시 → 익명 자식 객체
    • 인터페이스 구현시 → 익명 구현 객체

☑️ 익명 자식 객체

: 부모 클래스를 상속 받아 생성

new 부모생성자(매개값,...) {
//필드
//메소드
} 

→ 중괄호 블록 안의 필드와 메소드는 익명 자식 객체가 가져야 할 멤버로, 중괄호 블록 안에서만 사용 가능

→ 주로 부모 메소드를 재정의 하는 코드가 들어감

📌 필드에 익명 자식 객체 대입 하는 경우

//필드에 익명 자식객체 대입
private Tire tire2 = new Tire() {
	@override
	public void roll() {
		System.out.println("익명자식객체입니다")
	}
}

이런식으로 new 부모생성자()하고 바로 중괄호 {} 

📌로컬 변수에 익명 자식 객체 대입

public void run2() {
//로컬변수에 익명자식객체 대입
	Tire tire = new Tire() {
		@Override
		public void roll() {
			System.out.println("익명자식객체입니다")
	}
}
tire.roll();
} 

☑️ 익명 구현 객체

:인터페이스를 구현해서 생성

new 인터페이스() {
//필드
//메소드
}

→ 중괄호 블록 안의 필드와 메소드는 익명 구현 객체가 가져야 할 멤버로, 중괄호 블록 안에서만 사용 가능

→ 주로 인터페이스의 추상 메소드를 재정의 하는 코드가 들어감

📌 위의 익명 자식 객체와 유사하다

Comments