/ JAVAJUNGSUK

Ch7-45~50. 내부 클래스

자바의 정석 기초편

0. 목차



Chapter7. 객체지향 프로그래밍Ⅱ

Ch7 - 45. 내부 클래스의 제어자와 접근성

Ch7 - 46. 내부 클래스의 제어자와 접근성 예제1

Ch7 - 47. 내부 클래스의 제어자와 접근성 예제2

Ch7 - 48. 내부 클래스의 제어자와 접근성 예제3

Ch7 - 49. 내부 클래스의 제어자와 접근성 예제4

Ch7 - 50. 내부 클래스의 제어자와 접근성 예제5



Ch7 - 45. 내부 클래스의 제어자와 접근성


▶ 클래스 앞 제어자

▷ 일반적 클래스 앞 제어자 : (default), public 2개만 가능
▷ 내부 클래스 앞 제어자 : (default), public, private, protected 4개 다 가능
▷ 내부 클래스 ≒ 변수



Ch7 - 46. 내부 클래스의 제어자와 접근성 예제1


▶ static 멤버를 가질 수 있는 건 static 클래스 뿐!

▷ staitc 멤버는 객체 생성없이 사용 가능한 것
▷ static 클래스는 객체 생성 안해도 됨
▷ iv → cv 사용 가능
▷ iv ← cv 사용 불가
class Outer {
	class InstanceInner {
		int iv = 100;
		static int cv = 100; // ERROR! 인스턴스에서 static변수 → 선언 불가!
		final static int CONST = 100; // final static = 상수 → 선언 가능
	}

	static class StaticInner {
		int iv = 200;
		static int cv = 200; // static에서 static변수 → 선언 가능
	}

	void method() {
		class LocalInner {
			int iv = 300;
			static int cv = 300; // ERROR! Local에서 static변수 → 선언 불가!
			final static int CONST = 300; // final static = 상수 → 선언 가능
		}
	}
}
▷ final static은 상수, 변수X → static 클래스 아니어도 사용 가능
▷ final static 상수는 객체 생성 없이 바로 호출도 가능
  • System.out.println(InstanceInner.CONST);
  • System.out.println(StaticInner.cv);
  • System.out.println(LocalInner.cv);
    • 지역 내부 클래스method 안에서만 사용 가능!



Ch7 - 47. 내부 클래스의 제어자와 접근성 예제2


▶ static 메서드에서 instance 직접 사용 불가!

▷ iv → cv 사용 가능
▷ iv ← cv 사용 불가
▷ 같은 원리로 static에서 instance 직접 사용 불가!
class Outer {
	class InstanceInner { }

	static class StaticInner { }

	InstanceInner iv = new InstanceInner();
	static StaticInner cv = new StaticInner();
	
	static void staticMethod() {
		InstanceInner obj1 = new InstanceInner(); // ERROR! static 메서드 안에서 instance 직접 접근 불가
		StaticInner obj2 = new StaticInner();
	}
	
	void instanceMethod() {
		InstanceInner obj1 = new InstanceInner();
		StaticInner obj2 = new StaticInner(); // instance 메서드에서는 static 사용 가능
		LocalInner lv = LocalInner(); // ERROR! 지역 내부 클래스는 메서드 안에서만
	}
	
	void method() {
		class LocalInner {
			LocalInner lv = new LocalInner();
		}
	}
}



Ch7 - 48. 내부 클래스의 제어자와 접근성 예제3


▶ 내부 클래스 private 사용 가능!

▷ private : 같은 클래스만 사용가능
▷ 내부 클래스 : 같은 클래스 안에 있는 다른 클래스
▷ 내부 클래스도 같은 클래스
class Outer {
	private int outerIv = 0;
	static int outerCv = 0;

	class InstanceInner {
		int iv = outerIv; // 외부 클래스의 private 사용 가능
		int cv = outerCv;
	}

	static class StaticInner {
		int siv = outerIv; // ERROR! static → 인스턴스 멤버 접근 불가
		static int scv = outerCv;
	}
}

▶ 지역 내부 클래스에서는 변수 사용 불가, 상수만 접근 가능

▷ 상수 : final int
▷ JDK1.8 부터는 final 생략가능
int lv = 0;
int LV = 0; // final int lv = 0;
  • 겉보기에 똑같음
  • 어떻게 구분?
  • 값이 바뀌지 않으면 상수로 간주
▷ 상수만 접근 가능한 이유는 상수는 constant pool이란 곳에서 따로 관리
  • method는 자기 할 거 다 하면 없어짐
  • 근데 상수는 constant pool가면 있음
class Outer {
	void method() {
		int lv = 0;
		final int LV = 0;
		
		class LocalInner {
			int iv = outerIv;
			int cv = outerCv;
			
			int lv = lv; // 원래는 ERROR! 외부 클래스 지역변수는 상수만 접근 가능, JDK1.8부터는 에러 아님
			int lV = LV;
		}
	}
}
  • method보다 method 안에 있는 내부 클래스의 객체가 더 오래 살 수도 있음
    • method는 자기 할 거 다하면 없어져서


Ch7 - 49. 내부 클래스의 제어자와 접근성 예제4


▶ 인스턴스 사용하려면, 외부 클래스 인스턴스 먼저 생성!

▷ 인스턴스 사용하려면? 외부 클래스 인스턴스 생성 → 내부 클래스 인스턴스 생성
▷ static은? 외부 클래스 인스턴스 생성 안해도 됨, 바로 내부 클래스 인스턴스 생성
  • 단, 생성 시 외부 클래스 이름.내부 클래스 이름 = new 외부 클래스 이름.내부 클래스 이름
class Outer {
  class InstanceInner {
    int iv = 100;
  }
  
  static class StaticInner {
    int iv = 200;
    static int cv = 300;
  }
  
  void method() {
    class LocalInner {
      int iv = 400;
    }
  }
}

class Test {
  public static void main(String[] args) {
  Outer o = new Outer(); // 외부 클래스의 인스턴스 먼저 생성
  Outer.InstanceInner oi = o.new InstanceInner(); // 인스턴스 클래스의 인스턴스 생성 가능
  
  Outer.StaticInner s = new Outer.StaticInner(); // static 내부 클래스는 외부 클래스 인스턴스를 먼저 생성 안해도 됨
  }
}



Ch7 - 50. 내부 클래스의 제어자와 접근성 예제5


▶ 변수의 위치 파악

▷ 외부 클래스의 iv
▷ 내부 클래스의 iv
▷ lv
class Outer {
	int value = 10; // 외부 클래스의 iv

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

		void method() {
			int value = 30; // lv
			System.out.println("value : " + value); // 가장 가까운 value
			System.out.println("this.value : " + this.value); // 내부 클래스의 iv
			System.out.println("Outer.this.value : " + Outer.this.value); // 외부 클래스의 iv
		}
	}
}

class Test {
	public static void main(String[] args) {
		Outer o = new Outer(); // 외부 클래스의 인스턴스 먼저 생성
		Outer.Inner inner = o.new Inner(); // 인스턴스 클래스의 인스턴스 생성 가능

		inner.method();
	}
}

// console
value : 30
this.value : 20
Outer.this.value : 10