내부 클래스

cutiepazzipozzi·2023년 5월 23일
1

지식스택

목록 보기
28/35
post-thumbnail

지난번 단원은 정석의 키워드만 보고 공식 문서 찾아다니면서 읽으니까 뭔가 덜 수동적인 거 같은 느낌이 들어서, 앞으로는 섞어서 내용을 작성해볼까 한다.

[내부 클래스]

내부 클래스란?

= 클래스 내에 선언된 클래스 (JDK 1.1 이후 추가된 개념)

  • 그럼 왜 써? (사실 장점 얘기하기 위한 빌드업)
    -> 두 클래스가 서로 긴밀한 관계를 가지니까!
    -> 두 멤버들 간 쉽게 접근이 가능 + 불필요한 클래스 감춤
    -> 코드의 복잡성을 줄일 수 있음
(내부 클래스 예시)

class A { //A는 외부 클래스
	//...
    class B { //B는 내부 클래스
    	//...
    }
}
  • But GUI 어플리케이션의 이벤트 처리(ex. AWT, Swing)외에는 잘 사용하지 않을 정도로 사용 빈도가 높지 않다.

내부 클래스의 종류와 특징

= 변수의 선언위치에 따라 갈림!

  • 변수를 선언하는 것과 같은 위치에 선언이 가능
  • 선언위치에 따른 유효범위와 접근성이 달라짐
  1. 인스턴스 클래스
  • 외부 클래스의 멤버변수 선언 위치에 선언
  • 외부 클래스의 인스턴스 멤버처럼 다뤄짐
  • 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용됨
  1. static 클래스
  • 외부 클래스의 멤버변수 선언 위치에 선언
  • 외부 클래스의 static 멤버처럼 다뤄짐
  • 주로 static 메서드에서 사용될 목적으로 선언
  1. local 클래스
  • 외부 클래스의 메서드 or 초기화 블럭에 선언
  • 선언된 영역 내부에서만 사용
  1. 익명 클래스
  • 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스 (일회용)

내부 클래스의 선언

class Outer {
	class InstanceInner {}
    static class StaticInner {}
    
    void myMethod() {
    	class LocalInner {}
    }
}

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

위의 내부 클래스 선언 예시에서 InstanceInnerStaticInnerOuter의 멤버변수와 같은 위치에 선언되며, 같은 성질을 갖는다.

=> 따라서 인스턴스 멤버과 static 멤버간의 규칙이 내부 클래스에도 똑같이 적용된다.

  • abstract, final과 같은 제어자의 사용이 가능
  • private, protected와 같은 접근제어자도 사용 가능
class InnerEx1 {
	class InstanceInner {
    	int iv = 100;
        final static int CONST = 100;
    }
    
    static class StaticInner {
    	int iv = 200;
        static int cv = 200;
    }
    
    void myMethod() {
    	class LocalInner {
        	int iv = 300;
        }
    }
    
    public static void main(String[] args) {
    	System.out.println(InstanceInner.CONST);
        System.out.println(StaticInner.cv);
    }
    
    //출력결과
    //100
    //200
}
  • 위의 클래스들 중 StaticInner만 static 멤버를 가질 수 있다.
    but final+static인 상수는 모든 내부 클래스에서 정의가 가능하다.
class InnerEx2 {
	class InstanceInner {}
    static class StaticInner {}
    
    InstanceInner iv = new InstanceInner();
    static StaticInner cv = new StaticInner();
    
    static void staticMethod() {
    	StaticInner obj2 = new StaticInner();
    }
}
void myMethod() {
	int lv = 0;
    final int LV = 0;
    
    class LocalInner {
    	int liv = outerIv;
        int liv2 = outerCv;
        int liv3 = lv; //에러 발생!!!!!!
        int liv4 = LV;
    }
}
  • 지역 클래스는 final이 붙은 지역 변수에만 접근 가능하다!
    (메서드가 수행을 마쳐 지역변수가 소멸된 시점에도, 지역 클래스의 인스턴스가 소멸된 지역변수를 참조하려는 경우가 발생할 수 있기 때문)
class Outer {
	class InstanceInner {
    	int iv = 100;
    }
    static class StaticInner {
    	int iv = 200;
        static int cv = 300;
    }
    void myMethod() {
    	class LocalInner {
        	int iv = 400;
        }
    }
}

class InnerEx4 {
	public static void main(String[] args) {
    	Outer oc = new Outer();
        Outer.InstanceInner ii = oc.new InstanceInner();
        
        System.out.println("ii.iv: "+ii.iv);
        System.out.println("Outer.StaticInner.cv: "+Outer.StaticInner.cv);
        
        Outer.StaticInner si = new Outer.StaticInner();
        System.out.println("si.iv : "si.iv);
    }
}

------
InnerEx4.class
Outer.class
Outer$InstanceInner.class
Outer$StaticInner.class
Outer$1LocalInner.class

컴파일 시 '외부 클래스명$내부 클래스명.class' 형태로 파일명 생성됨
  • 외부 클래스가 아닌 다른 클래스에서 내부 클래스 생성 후 내부 클래스의 멤버에 접근

익명 클래스

= 일회용 클래스(클래스의 선언과 객체의 생성을 동시에 하므로 단 한번만 사용)
= new 조상클래스이름() {} or new 구현인터페이스이름() {}

  • 이름 X => 생성자 X
  • 단 하나의 클래스 or 인터페이스 구현
class InnerEx6 { //세가지 모두 익명클래스
	Object iv = new Object() {void method(){} };
    static Object cv = new Object() {void method() {} };
    
    void myMethod() {
    	Object lv = new Object() {void method() {} };
    }
}
  • 컴파일 시 이름이 없어 외부클래스명$숫자.class로 파일명 결정
import java.awt.*;

class InnerEx8 {
	public static void main(String[] args) {
    	Button b = new Button("start");
        b.addActionListner(new ActionListner() {
        	public void actionPerformed(ActionEvent e) {
            	System.out.println("ActionEvent occured!!!");
            }
        } //익명 클래스 끝
    }
}

참조

자바의 정석, 2nd Edition.

profile
노션에서 자라는 중 (●'◡'●)

0개의 댓글