본문 바로가기
수업(국비지원)/Java

[Java] chap10 : 내부 클래스 - 내부 클래스

by byeolsub 2023. 4. 16.
  • 내부 클래스
내부 클래스 : 클래스 내부에 존재하는 클래스
             자료형은 외부클래스명.내부클래스명 
  
   외부클래스 : 내부클래스를 멤버로 인식한다.
   내부클래스 :
      1. 인스턴스 내부클래스 : 객체화시 외부클래스의 객체화가 먼저되어야한다.
      2. Static내부클래스 : new 외부클래스명.내부클래스() 객체화 됨.
                         외부클래스의 객체화 필요없음.
      3. 지역내부클래스 : 메서드 내에 선언된 클래스. 메서드 내에서만 객체화 가능.   

 

📌

package chap10;

class Outer1 { //외부 클래스 
	class InstanceInner extends Object { //인스턴스 내부 클래스
		int iv = 100; //인스턴스 내부 클래스의 멤버이고 인스턴스 변수
		static int cv = 10; //인스턴스 내부 클래스의 멤버이고 클래스 변수
		final static int MAX = 200; //인스턴스 내부 클래스의 멤버이고 상수
	}
	static class StaticInner { //static 내부클래스
		int iv = 300; //인스턴스 변수
		static int cv = 20; //클래스 변수
		final static int MAX = 400; //상수
	}
	void method() { //지역변수 - 해당 메소드안에서만 사용 가능한 변수
		class LocalInner { //지역내부클래스(Local Inner) : 메서드 내부에서만 사용가능
			int iv = 500;
			static int cv = 600;
			final static int MAX = 700;
		}
		LocalInner lc = new LocalInner(); //객체화
		System.out.println("LocalInner.iv:"+lc.iv); 
		System.out.println("LocalInner.cv:"+LocalInner.cv);
		System.out.println("LocalInner.MAX:"+LocalInner.MAX);

	}
	void method2() { //인스턴스 멤버
//		LocalInner lc = new LocalInner(); //method() 사용 가능 클래스
		InstanceInner ii = new InstanceInner();
		System.out.println("InstanceInner.iv:"+ii.iv);
		System.out.println("InstanceInner.cv:"+InstanceInner.cv);
		StaticInner si = new StaticInner();
		System.out.println("StaticInner.iv:"+si.iv);
		System.out.println("StaticInner.cv:"+StaticInner.cv);
	}
}
public class InnerEx1 {
	public static void main(String[] args) {
		//InstanceInner 객체화 <= 외부클래스의 객체화가 먼저다.
		Outer1 out = new Outer1(); 
		out.method();
		out.method2();
		Outer1.InstanceInner ii = out.new InstanceInner();
		System.out.println("InstanceInner.iv:"+ii.iv);
		System.out.println("InstanceInner.cv:"+Outer1.InstanceInner.cv);
		System.out.println("InstanceInner.MAX:"+Outer1.InstanceInner.MAX);
		//StaticInner 객체화
		Outer1.StaticInner si = new Outer1.StaticInner();
		System.out.println("StaticInner.iv:"+si.iv);
		System.out.println("StaticInner.cv:"+Outer1.StaticInner.cv);
		System.out.println("StaticInner.MAX:"+Outer1.StaticInner.MAX);
		//내부 클래스의 객체도 Object 클래스의 하위클래스임
		if(ii instanceof Object) {
			System.out.println("ii 객체는 Object 객체임");
		}
		if(si instanceof Object) {
			System.out.println("si 객체는 Object 객체임");
		}
	}
}

💡

  • 지역 내부 클래스의 멤버 메서드 내에서 메서드의 지역변수 접근시 지역변수는 상수화 되어야 한다.
  • 만약 지역변수의 변경이 없다면 상수로 취급한다.
  • 지역변수가 변경이 되면 상수로 취급하지 않으므로 오류 발생.

📌

package chap10;
class Outer2 {
	private int outeriv = 10;
	private static int outercv = 20;
	class InstanceInner {
		int iiv = outeriv; // 외부클래스의 private 멤버 접근 가능. why? 같은 멤버로 보기 때문에
		int iiv2 = outercv;
	}
	static class StaticInner {
//오류:	int siv = outeriv; // why? 클래스 멤버에서 인스턴스 멤버를 호출하는 것이여서 
		int siv = new Outer2().outeriv;
		static int scv = outercv;
	}
	void method(int pv) {
		int n = 0;
//오류:	pv += 1; //지역변수 => 값을 변경 하였다는 건 상수가아니다 라는 소리. 
                 //            그래서 오류 발생
//오류:	n = 100;
/*
 * 지역 내부 클래스의 멤버 메서드 내에서 메서드의 지역변수 접근시 
 * 지역변수는 상수화 되어야 한다.
 * 만약 지역변수의 변경이 없다면 상수로 취급한다.
 * 지역변수가 변경이 되면 상수로 취급하지 않으므로 오류 발생
 */
		class LocalInner {
			int liv = outeriv; //외부클래스에 있는 private 멤버에 접근 가능
			int lcv = outercv;
			void method(int num) { //지역내부클래스의 멤버 메서드
				num+=10;
				liv+= 100;
				System.out.println("num="+num);
				System.out.println("liv="+liv);
				System.out.println("lcv="+lcv);
				System.out.println("n="+n);
				System.out.println("pv="+ pv);
				outeriv++;
				System.out.println("outeriv="+ outeriv);
			}
		}
		//LocalInner 객체화. method 호출
		LocalInner li = new LocalInner();
		li.method(100);
	}
}

public class InnerEx2 {
	public static void main(String[] args) {
		//InstanceInner, StaticInner, method() 호출하기
		Outer2 o = new Outer2();
		Outer2.InstanceInner ii = o.new InstanceInner();
		Outer2.StaticInner si = new Outer2.StaticInner();
		o.method(10);
	}
}

  • 내부 클래스에서 사용되는 this
  내부 클래스의 객체에서 this. : 내부클래스의 객체를 참조
  외부 클래스의 멤버 접근
     외부클래스명.this.멤버명 으로 호출

 

📌

package chap10;

class Outer3 {
	int iv = 10;
	int iv2 = 20;
	class InstanceInner {
		int iv = 100;
		void method1() {
			int iv = 300;
			System.out.println("iv="+iv);
			System.out.println("iv2="+iv2); //외부클래스의 멤버
//오류:System.out.println("this.iv2="+this.iv2); 
//why? 외부클래스의 멤버는 this.를 쓸 수 없다.(super 도 사용 불가.)
			System.out.println("this.iv="+this.iv);
			System.out.println("Outer3.this.iv="+Outer3.this.iv); //외부클래스의 멤버.  
			System.out.println("Outer3.this.iv2="+Outer3.this.iv2);
		}
	}
}
public class InnerEx3 {
	public static void main(String[] args) {
		Outer3.InstanceInner ii = new Outer3().new InstanceInner();
		ii.method1();
	}
}