TIL) Java - 내부 클래스

oatraspberry·2022년 12월 13일
post-thumbnail

내부 클래스(inner class)

클래스 안의 클래스
클래스 내부에서만 사용할 목적으로 만드는 클래스

class A { // B의 외부 클래스
	...
	class B { // A의 내부 클래스
		...
	}
    ...
}

내부 클래스의 장점

  • 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
  • 코드의 복잡성을 줄일 수 있다. (캡슐화)

내부 클래스의 종류

내부 클래스의 종류와 유효범위(scope)는 변수와 동일함

인스턴스 내부 클래스

외부 클래스 생성 후 생성되며 외부 클래스의 멤버변수 선언위치에 선언함.
외부 클래스의 인스턴스 멤버처럼 다루어진다.
주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언된다.
객체 내부에 멤버의 형태로 존재함.
정적 변수, 정적 메서드 사용할 수 없음.
외부 클래스의 참조 변수를 이용하여 내부 클래스 사용한다
내부 클래스가 private이 아니면 다른 외부 클래스에서도 객체 생성 가능
클래스 내부에서만 사용할 목적이면 private으로 선언

아우터클래스 a = new 아우터클래스(); // 아우터클래스 객체 생성
아우터클래스.이너클래스 b = 아우터클래스객체.new 이너클래스(); // 이너클래스 객체 생성

인스턴스 멤버 이너클래스는 힙메모리 내의 아우터클래스 객체 내에 생성되기 때문에 아우터 클래스 객체를 먼저 생성하여야 함.

정적(static) 내부 클래스

외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static 멤버처럼 다루어진다.
주로 외부 클래스의 static멤버, 특히 static 메서드에서 사용될 목적으로 선언된다.
*static -> 객체를 생성하지 않아도 만들어짐.
외부 클래스의 생성과 무관하게 사용함.
정적 내부 클래스 메서드에서 변수 사용 여부

특징

  • 아우터 클래스의 static 멤버만 접근 가능(static의 특징)
  • 생성 클래스명: 아우터클래스.class, 아우터클래스$이너클래스.class
아우터클래스.이너클래스 a = new 아우터클래스.이너클래스();

A.B b = new A.B();
b.bcd(); // 정적 멤버 이너 클래스

class A {
	int a = 3;
    static int b= 4;
    
    static class B {
    	void bcd() {
        	System.out.println(a); // X
            System.out.println(b); // O
            System.out.println("정적멤버이너클래스");
        }
    }
}

지역 내부 클래스

외부 클래스의 메서드나 초기화 블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다.
지역 변수와 같이 메서드 내부에서 정의하여 사용하는 클래스
메서드의 호출이 끝나면 메서드에 사용된 지역 변수의 유효성은 사라짐.
메서드 호출 이후에서 사용해야 하는 경우가 있으므로 지역 내부 클래스에서 사용하는 메서드의 지역 변수나 매개 변수는 final로 선언됨.

특징

  • 메서드 내부에서 정의된 클래스
  • 아우터(outer)클래스의 필드는 모두 접근 가능
  • 메서드 지역변수는 final만 사용 가능(final로 지정하지 않은 경우 컴파일러가 자동으로 지정됨)
  • 지역 이너클래스는 static 지정 불가능함.
아우터클래스.class
아우터클래스$+번호이너클래스.class

class A {
	int a = 3; // 필드
    void abc() {
    	int b  = 5; // 지역변수. 지역 클래스에서 사용되는 경우 자동으로 final 추가
        
        class B {
        	void bcd() {
            System.out.println(a) ; // 필드 O
            System.out.println(b); // 지역변수 O
            a = 7; // 필드값 변경O
            // b = 7; // 지역변수값 변경X
        }
    }
    B bb = new B();
    bb.bcd();
  	}
}

익명 내부 클래스

익명(이름을 알 수 없음)+이너클래스

이름이 없는 클래스
주로 하나의 인터페이스나 하나의 추상 클래스를 구현하는데 사용함.
인터페이스나 추상 클래스 자료형의 변수에 직접 대입하여 생성하거나 지역 내부 클래스의 메서드 내부에서 생성하여 반환할 수 있음.
안드로이드 widget의 이벤트 핸들러를 구현할 때 많이 사용함.
익명이너클래스를 사용하는 경우 이름이 없어 한번에 객체를 2개 이상 생성 불가능

class A1 {
	C b = new B(); // 필드
    
    void abc() { // 메서드
    	b.bcd();
    }
    
    class B implements C { // 인스턴스 이너 클래스
    	public void bcd() {
        	System.out.println(...);
        }
   }
}
class A2 {

	C b = new C() {
    	public void bcd() {
        	System.out.println(...);
        }
    }; // C를 상속받아 bcd() 메서드를 오버라이딩한 익명 이너클래스의 객체
    
	void abc() {
    	b.bcd();
    }
}

내부 클래스의 제어자와 접근성

내부 클래스의 제어자는 변수에 사용 가능한 제어자와 동일

https://www.youtube.com/watch?v=cZJyRGX2VoM&list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp&index=95

이너인터페이스

클래스 안에 선언된 인터페이스

특징

  • 아우터 클래스와 밀접한 관계가 있는 경우에 정의
  • UI의 이벤트 처리에 가장 많이 사용(클릭, 터치 등)
  • static을 생략한 경우 컴파일러는 자동으로 static 삽입
  • 이너인터페이스는 정적(static)이너인터페이스만 가능(static 생략시 자동 추가)

생성클래스명: A.class, A$B.class

// 방법1. 인터페이스 구현 클래스 생성 및 객체 생성
class C implements A.B {
	public void bcd() {
    	...
    }
}

C c = new C();
c.bcd();

// 방법2. 익명이너클래스 사용
A.B a = new A.B() { // A.B -> static 클래스와 유사함
	public void bcd() {
    	...
    }
};

a.bcd();
profile
개발자가 될테야

0개의 댓글