Language/JAVA

열한번째날 [중첩 클래스와 중첩 인터페이스]

구일일구 2022. 8. 4. 20:43
반응형

중첩클래스 = 내부클래스  : 클래스 안의 클래스

목차

1. 중첩 클래스와 중첩 인터페이스란?

2. 중첩 클래스

3. 중첩 클래스의 접근 제한

4. 중첩 인터페이스

5. 익명 객체


1. 중첩 클래스와 중첩 인터페이스란?

* 중첩 클래스(Nested Class)

- 클래스가 여러 클래스와 관계를 맺을 경우 : 독립적 선언

- But 특정 클래스와 관계를 맺을 경우 : 관계 클래스를 클래스 내부에 선언 ➡️ 중첩 클래스(Nested Class)

*클래스가 다른 클래스에서 가져다 쓰려면 상속, 객체 생성 등 필요한데,

중첩 클래스에선 그 클래스 안에 있는 모든 것들을 마음대로 가져다 쓸 수 있기 때문에 중첩 클래스를 사용한다. 

 

* 장점 

- 두 클래스의 멤버들을 서로 쉽게 접근할 수 있음

- 외부에 불필요한 관계 클래스를 감추며 코드의 복잡성을 줄일 수 있음

 

* 중첩 클래스 : 클래스 블록 안에 들어간 클래스

class A{
	class B{ ... }
}

 

* 중첩 인터페이스 : 클래스 블록 안에 들어간 인터페이스

- 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해서

- UI 컴포넌트 내부 이벤트 처리에 많이 활용

class A{
	interface B{...}
}

2. 중첩 클래스

* 중첩 클래스의 분류

선언 위치에 따른 분류 선언 위치 설명
멤버 클래스 인스턴스
멤버 클래스
class A{
    class B {...}
}
A 객체를 생성해야만
사용할 수 있는 B 중첩 클래스
정적
멤버 클래스
class A{
    static class B{...}
}
A 클래스로 바로 접근할 수 있는
B 중첩 클래스
로컬 클래스 class A{
    void method(){
        class B{...}
    }
}
method()가 실행할 때만
사용할 수 있는 B 중첩 클래스

- 멤버 클래스 : 인스턴스 멤버 클래스 : 필드,생성자, 메소드 자리에 들어가는 클래스

- 멤버 클래스 : 정적 멤버 클래스 : 위에랑 똑같은데 static 붙은거

- 로컬 클래스 : 메소드 안에 들어간 클래스

 

* 멤버 클래스 바이트 코드 파일 이름 : $ 포함

 

* 로컬 클래스 바이트 코드 파일 이름 : $1 포함

 

* 인스턴스 멤버 클래스

- static 키워드 없이 선언된 클래스 : 인스턴스 필드 & 인스턴스 메소드 

- 안에 static 붙일 수 없음 : A클래스에 객체가 생성되면 힙메모리에 들어가기 때문에 

class A{
    class B{
        b(){}
        int field1
        void method1(){}
    }
}
A 클래스 외부에서 인스턴스 멤버 클래스 B 객체 생성 방법
A a = new A();
A.B b = a.new B();
b.field1 = 3
b.method1();

 

* 정적 멤버 클래스

- static 키워드로 선언된 클래스, 모든 종류의 필드와 메소드 선언 가능함(인스턴스필드&메소드, 정적필드&메소드)

- 객체 만들기도 인스턴스 멤버 클래스보다 쉬움

static class C{
    C(){}
    int field1;
    static int field2;
    void method1(){}
    static void method2(){}
}
A 클래스 외부에서 정적 멤버 클래스 C 객체 생성 방법
A.C c = new A.C();    
c.field1 = 3;    //인스턴스 필드 사용    
c.method1();    //인스턴스 메소드 호출
A.C.field2 = 3;    //정적 필드 사용
A.C.method2();    //정적 메소드 호출

 

* 로컬 클래스

- 메소드 내에서만 사용

- 접근제한자(public, private) 및 static 붙일 수 없음 : 메소드 내에서만 사용하기 때문에 필요 없음

- 로컬 클래스 내부 사용 : 인스턴스 필드, 인스턴스 메소드만 선언 가능 (정적 필드&메소드 X)

- 로컬 클래스는 메소드가 실행될 때 메소드 내에서 객체를 생성하고 사용해야 함

void method(){
    class D{
        D(){}
        int field1;
        //static int field2;
        void method1(){}
        //static void method2()
    }
    D d = new D();
    d.field1 = 3;
    d.method1();
}

3. 중첩 클래스의 접근 제한

* 바깥 필드와 메소드에서 사용 제한

- 인스턴스 멤버 클래스 : 인스턴스 필드 초기값, 인스턴스 메소드에서 객체 생성 가능 / 정적 필드 초기값X, 정적 메소드 객체 생성X

- 정적 멤버 클래스 : 모든 필드 초기값, 모든 메소드에서 객체 생성 가능

 

* 멤버 클래스에서 사용 제한

- 멤버 클래스 내부에서 바깥 클래스의 필드와 메소드를 접근할 때에도 제한이 있음

- 인스턴스 멤버 안 : 바깥 클래스 모든 필드, 메소드 가능

- 정적 멤버 안 : 바깥 정적 필드, 메소드 접근 가능 / 인스턴스 필드 , 메소드 접근 불가능

 

* 로컬 클래스에서 사용 제한 : 이해가 안대요..

- 로컬 클래스 내부 : 바깥 클래스 필드와 메소드 사용 가능

- 메소드의 매개 변수나 로컬 변수를 로컬 클래스에서 사용할 때 : 로컬 클래스의 객체는 메소드 실행이 끝나도 힙 메모리에 존재해서 계속 사용될 수 있다. 매개 변수나 로컬 변수는 메소드 실행이 끝나면 스택 메모리에서 사라지기 대문에 로컬 객체에서 사용할 경우 문제가 발생. 자바는 이 문제를 해결하기 위해 컴파일 시 로컬 클래스에서 사용하는 매개 변수나 로컬 변수의 기억 장소를 로컬 클래스 내부에 복사해 두고 사용. 그리고 매개 변수나 로컬 변수가 수정되어 기억 장소가 변경되면 로컬 클래스에 복사해 둔 기억 장소와 달라지는 문제를 해결하기 위해 매개 변수나 로컬 변수를 final 로 선언해서 수정을 막는다.

- 결론적으로 로컬 클래스에서 사용 가능한 것은 final로 선언된 매개 변수와 로컬 변수뿐. 

- 자바 8부터 final 키워드 없이 선언된 매개 변수와 로컬 변수를 사용해도 컴파일 에러가 나지 않는다. : final 선언을 하지 않아도 여전히 값을 수정할 수 없는 final의 특성을 갖는다는 것. final 키워드 존재 여부의 차이점은 로컬 클래스의 복사 위치. final 키워드가 있다면 로컬 클래스의 메소드 내부에 지역 변수로 복사되지만, final 키워드가 없다면 로컬 클래스의 필드로 복사됨

- 로컬 클래스의 내부 복사 위치에 신경 쓸 필요 없이 로컬 클래스에서 사용된 매개 변수와 로컬 변수는 모두 final 특성을 갖는다는 것만 알면 됨

 

* 중첩 클래스에서 바깥 클래스 참조 얻기

- this : 중첩 클래스에서 사용하면, 중첩 클래스의 객체 참조가 된다

중첩 클래스 내부에서 객체 참조 얻는 법

this.필드	//중첩 클래스의 필드
this.메소드() //중첩 클래스의 메소드
중첩 클래스 내부에서 바깥 클래스 객체 참조 얻는 법

바깥클래스.this.필드
바깥클래스.this.메소드();

4. 중첩 인터페이스

class A{
    interface I{
        void method();
    }
}

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

 

* 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위함

- 특히 UI 프로그래밍에서 이벤트를 처리할 목적으로 많이 활용 됨


5. 익명 객체

* 익명 객체 : 이름이 없는 객체

- 단독 생성 불가 : 클래스 상속 or 인터페이스 구현해야 생성 가능

- 사용 위치 : 필드 초기값, 로컬변수 초기값, 매개변수의 매개값으로 주로 대입

- 목적 : UI 이벤트 처리 객체, 스레드 객체를 간편하게 생성할 목적

 

* 익명 자식 객체 생성 - 초기값 설정에 주목

class A{
	Parent field = new Parent(){
		int childField;
		void childMethod(){}
		@Override
		void parentMethod(){}
	};
}

 

* 익명 객체에 정의된 필드와 메소드

- 익명 객체 내부에서만 사용

- 외부에서는 익명 객체의 필드와 메소드에 접근할 수 없음

이유 : 익명 객체는 부모 타입 변수에 대입되므로 부모 타입에 선언된 것만 사용 가능

 

* 익명 구현 객체 생성

인터페이스 [필드|변수] = new 인터페이스(){
//인터페이스에 선언된 추상 메소드의 실제 메소드 선언
//필드
//메소드
};
반응형