자바의 정석 - 내부 클래스의 제어자와 접근성

Yohan·2024년 1월 29일
0

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

  • 내부 클래스의 제어자는 변수에 사용 가능한 제어자와 동일
    (private, protected, (default), public)
class Outer {
	private int iv = 0;
    protected static int cv = 0;
    
    void myMethod() {
    	int lv = 0;
    }
}
class Outer {
	private class InstanceInner {}
    protected static class StaticInner {}
    
    void myMethod() {
    	class LocalInner {}
    }
}

예제1

class Ex {
	// 인스턴스 내부 클래스
	class InstanceInner {
    	int iv = 100;
        static int cv = 100; // error, static변수 선언 불가
        final static int CONST = 100; // final static은 상수이므로 허용
    }
    
    // static 내부 클래스
    static class StaticInner {
    	int iv = 200;
        static int cv = 200; // static클래스만 static 멤버를 정의할 수 있다.
    }

    void myMethod() {
   		// 지역 내부 클래스
    	class LocalInner {
        	int iv = 300;
            static int cv = 300; // error, static변수 선언 불가
            final static int CONST = 300; // final static은 상수이므로 허용
        }
        
        int i = LocalInner.CONST; // Ok
    }
    
    public static void main(String args[]) {
    	System.out.println(InstanceInner.CONST);
        System.out.println(StaticInner.cv);
        System.out.println(LocalInner.CONST); // error, 지역 내부 클래스는 메서드 내에서만 사용가능
    }
}

예제2

  • static 메서드 : static멤버 접근 가능
  • 인스턴스 메서드 : 인스턴스멤버와 static멤버 모두 접근 가능
class Ex {
	class InstanceInner {}
    static class StaticInner {}
    
    InstanceInner iv = new InstanceInner(); // 인스턴스멤버끼리는 직접 접근 가능
    static StaticInner cv = new StaticInner(); //  static멤버끼리는 직접 접근 가능
    
    static void staticMethod() { // static멤버는 인스턴스멤버에 직접 접근 불가
    	InstanceInner obj1 = new InstanceInner(); // X
        StaticInner obj2 = new StaticInner();
    }
    
    void instanceMethod() { // 인스턴스메서드에서는 인스턴스멤버와 static멤버 모두 접근 가능
    	InstanceInner obj1 = new InstanceInner();
        StaticInner obj2 = new StaticInner();
        LocalInner lv = new LocalInner(); // 지역 내부 클래스는 외부에서 접근할 수 없다.
    }
    
    void myMethod() {
    	class LocalInner {}
        LocalInner lv = new LocalInner();
    }
}

예제3

  1. 내부클래스에서 외부클래스의 private멤버도 접근 가능
  2. 지역 내부 클래스를 감싸고 있는 메서드의 상수만 사용가능
class Outer {
    private int outerIv = 0;
    static int outerCv = 0;

    class InstanceInner {
        int iiv = outerIv; // 1. 내부클래스에서 외부클래스의 private멤버도 접근 가능
        int iiv2 = outerCv;
    }

    static class StaticInner {
        int siv = outerIv; // static 클래스는 외부 클래스의 인스턴스멤버에 접근할 수 없다.
        static int scv = outerCv;
    }

    void myMethod() {
        final int lv = 0; // 값이 바뀌지 않는 변수는 상수로 간주 (final 생략가능)
        final int LV = 0; // 상수, JDK 1.8 ~ final 생략가능

        class LocalInner { // 2. 지역 내부 클래스를 감싸고 있는 메서드의 상수만 사용가능
            int iiv = outerIv;
            int iiv2 = outerCv;
            // 외부클래스의 지역변수는 final이 붙은 변수(상수)만 접근 가능

        }
    }
}

예제4

class Outer2 {
    class InstanceInner {
        int iv = 100;
    }

    static class StaticInner {
        int iv = 200;
        static int cv = 300;
    }

    void myMethod() {
        class LocalInner {
            int iv = 400;
        }
    }
}

class Ex {
    public static void main(String[] args) {
        Outer2 oc = new Outer2(); // 1. 외부 클래스의 인스턴스를 먼저 생성해야 인스턴스 클래스의
        Outer2.InstanceInner ii = oc.new InstanceInner(); // 인스턴스를 생성 가능

        System.out.println("ii iv :" + ii.iv);
        System.out.println("Outer2.StaticInner.cv :" + Outer2.StaticInner.cv);

        // 2. static 내부 클래스의 인스턴스는 외부 클래스를 먼저 생성하지 않아도 된다.
        Outer2.StaticInner si = new Outer2.StaticInner();
        System.out.println("si.iv" + si.iv);
    }
}

예제5

class Outer3 {
    int value = 10; // 외부 클래스의 iv

    class Inner {
        int value = 20; // 내부 클래스의 iv

        void method1() {
            int value = 30; // 지역변수 iv
            System.out.println("value :" + value); // 지역변수 iv
            System.out.println("this.value :" + this.value); // 내부 클래스의 iv
            System.out.println("Outer3.this.value :" + Outer3.this.value); // 외부 클래스의 iv
        }
    }
}

class Ex {
    public static void main(String[] args) {
        Outer3 outer = new Outer3();
        Outer3.Inner inner = outer.new Inner();
        inner.method1();
    }
}
profile
백엔드 개발자

0개의 댓글