본문 바로가기

카테고리 없음

내부 클래스(inner class)

내부 클래스란 클래스를 클래스 안에 선언하는 것이다. 이는 클래스의 멤버변수로 클래스의 참조변수를 갖는 것과는 다르다.

 

내부 클래스의 종류

내부 클래스 종류 설명
인스턴스 클래스(Instance Class) 멤버변수 필드에 위치하며 위부 클래스와 관련된 작업에만 사용
스태틱 클래스(Static Class) 멤버변수 필드에 위치하며 static멤버나 static메서드에 관련된 작업에 사용된다. 
지역 클래스(Local Class) 외부 클래스의 메서드나 초기화 블록안에 위치한다. 해당 블록 내에서만 사용이 가능하다.
익명 클래스(Anonymous Class) 클래스의 선언과 객체의 생성을 동시에 하는 1회용 클래스이다.

 

 

아래와 같은 방식은 내부 클래스의 한 종류로 중첩클래스 또는 인스턴스클래스 라고 한다.

public class InnerClassTest{ // 외부 클래스 
	private int a = 10;
	
	public class InnerClass{ // 내부 클래스
		private int b = a + 10;
		
		public int getB() {
			return b;
		}
	}
	
	public int getA() {
		return a;
	}
	
	public static void main(String[] args) {
		InnerClassTest classTest = new InnerClassTest();
		System.out.println(classTest.getA()); // 10
		InnerClassTest.InnerClass ic = classTest.new InnerClass(); // classTest인스턴스에 내부클래스 생성
		System.out.println(ic.getB()); // 20
	}
}

inner class의 접근제어자는 멤버변수와 마찬가지로 public, protected, default, private 등이 가능하다. (멤버변수의 접근제어자와 동일)

 

 

Static Class

static class는 내부 클래스의 한 종류이며 static키워드가 붙은 내부 클래스를 의미한다. static클래스에서 외부 클래스의 멤버에 접글할 때에는 외부클래스의 객체를 생성한 뒤에 접글을 해야 하며, 내부클래스 중에서 static멤버를 가질 수 있는 것은 static내부클래스뿐이다.

※final static은 상수로 취급한다. 

 

public class InnerClassTest{ // 외부 클래스 
	private int a;
	public static int b;
	static { b++; }
	
	InnerClass staticCalssresult1;
	{ staticCalssresult1 = new InnerClass(); }

	static class InnerClass{ // static class
		public static int staticvalue;
		static { staticvalue = b + 1; }
		public void method() {
			System.out.println("static클래스의 메서드입니다.");
		}
	}
	
	public static void main(String[] args) {
		InnerClassTest classTest = new InnerClassTest();
		System.out.println(InnerClassTest.b);
		System.out.println(InnerClassTest.InnerClass.staticvalue); 
        // static 내부 클래스는 외부 클래스를 객체화 하지 않고도 바로 객체화가 가능하다.
        // 외부클래스이름.내부클래스이름 이 타입이 된다.
		InnerClassTest.InnerClass ic = new  InnerClassTest.InnerClass(); 
		ic.method();
		
		classTest.staticCalssresult1.method();
	}
	
}

 

Local Class

public class InnerClassTest{ // 외부 클래스 

	public void method() { // local class
		int localval1 = 10; // 값이 변경되 않는 한 상수로 취급
		final int localval2 = 20;
		// localval1 = 10000; // 이 주석을 풀면 int ivOflocalClass1 = localval1;이 문장에 오류가 방생
		
		class LocalClass{ // class선언 해당 메서드 내부에서만 사용
			final static int localClassStatic = 1000;
			// JDK1.8부터는 변수이지만 값이 바뀌지 않으면 상수로 취급한다.
			int ivOflocalClass1 = localval1; // method의 스택프레임이 삭제되면 지역변수도 소멸되는데 이 시점에도 LocalClass의 인스턴스는가 소멸된 지역변수를 참조하려는 문제점이 발생
			int ivOflocalClass2 = localval2; // 상수는 constant pool에 저장되기 때문에 stack frame이 소멸되어도 인트턴스에서 참조가 가능!
			
			public void localMethod() {
				System.out.println("local class입니다.");
				System.out.println("Local Class의 메서드입니다. 인스턴스변수들의 총합: " + (ivOflocalClass1 + ivOflocalClass2));
			}
		}
		
		LocalClass lc = new LocalClass(); // 인스턴스 생성
		lc.localMethod(); // method내에서 로컬클래스의 메서드 사용
		System.out.println("Local Class의 상수사용" + LocalClass.localClassStatic); // 상수취급이니 사용가능 
		
	}
	
	public static void main(String[] args) {
		InnerClassTest classTest = new InnerClassTest();
		classTest.method();
	}
	
}

 

 

 

내부클래스의 메서드에서 this를 사용하면 내부 클래스를 가리키고 외부클래스이름.this는 외부클래스를 가리킨다.

이름이 중복되는 변수를 this를 사용하지 않고 사용하면 가장 가까운 변수를 나타낸다.

public class InnerClassTest{ // 외부 클래스 
	private int a = 10;
	
	public class ThisTest{ // 내부 클래스
		private int a = 20;
		
		void method() {
			int a = 30;
			System.out.println(a); // 30
			System.out.println(this.a); // 20
			System.out.println(InnerClassTest.this.a); // 10
			System.out.println(InnerClassTest.ThisTest.this.a); // 20
		}
		
	}
	
	public static void main(String[] args) {
		InnerClassTest classTest = new InnerClassTest();
		InnerClassTest.ThisTest test = classTest.new ThisTest();
		test.method();

	}
}

 

 

 

 

 

Reference

  • 자바의정석(남궁성지음, 도우출판)