[Java] 내부 클래스

SeongWon Oh·2021년 8월 20일
0

Java

목록 보기
30/39
post-thumbnail

내부 클래스란?

  • 클래스 내부에 선언한 클래스로 일반적으로 내부 클래스를 감싸고 있는 외부 클래스와 연관이 있으며, 다른 외부 클래스에서 사용할 일이 거의 없는 경우에 내부 클래스를 선언해서 사용한다.

  • 내부 클래스는 중첩 클래스라고도 한다.

  • 내부 클래스의 종류

    • 인스턴스 내부 클래스
    • 정적(static) 내부 클래스
    • 지역(local) 내부 클래스
    • 익명(anonymous) 내부 클래스가

Instance Inner Class (인스턴스 내부 클래스)

  • 내부적으로 사용할 클래스를 선언하며 Private으로 선언하는 것을 권장한다.

  • private이 아닌 내부 클래스는 다른 외부 클래스에서 생성할 수 있다.

  • 외부 클래스가 생성된 후 생성된다.

👨🏻‍💻 Example Code1

package ch01;

class OutClass {
	private int num=10;
	private static int sNum =20;
	private InClass inClass;
	
	public OutClass() {
		inClass = new InClass();
	}
	
	// 내부 인스턴스
	// inner class는 주로 private로 구현
	private class InClass{
		int iNum = 100;
		
		//static int sInClass = 500;
		// inner class는 일반적으로 outer class가 생성이 된 후애 생성이된다.
		// 그래서 class생성전에 먼저 공간을 잡는 static 변수는 inner class에서 사용이 불가하다.
		
		void inTest(){
			System.out.println("OutClass num = " +num + "(외부 클래스의 인스턴스 변수)");
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수)");
			System.out.println("InClass inNum = " + iNum + "(내부 클래스의 인스턴스 변수)");
		}

	}
	
	public void usingClass() {
		inClass.inTest();
		// inner class내에 있는 method사용 예시
	}
}
public class InnerTest {
	public static void main(String args[]) {
		OutClass outClass = new OutClass();
		outClass.usingClass();
		
		/*// inner class가 private로 만들지 않으면 아래와 같이 바로 사용도 가능
		OutClass.InClass inner = outClass.new InClass();
		inner.inTest();
		*/
	}
}

Static Inner Class (정적 내부 클래스)

  • static으로 생성하여 외부 클래스와 무관하게 사용할 수 있다.

  • static variable과 static method를 사용한다.

  • 정적 내부 클래스는 일반 메서드와 정적 메서드에서의 변수 사용에 제약이 있다.

👨🏻‍💻 Example Code1

package ch01_1;

class OutClass {
	private int num=10;
	private static int sNum =20;

	
	// 정적 내부 클래스
	static class InStaticClass {
		int iNum = 100;
		static int sInNum = 1200;
		
		void inTest(){
			// 내부 인스턴스와 다르게 정적 내부 클래스는 static으로 만들어 진 것이라 외부 클래스의 
			// 인스턴스 생성 여부에 상관없이 생성이 된다.
			// 그래서 외부 인스턴스의 일반 인스턴스 변수는 정적 내부 클래스에서 사용이 불가능하다.
			//System.out.println("OutClass num = " +num + "(외부 클래스의 인스턴스 변수)");
			System.out.println("InStaticClass inNum = " + iNum + "(내부 클래스의 인스턴스 변수 사용)"); 
			System.out.println("InStaticClass sInNum = " + sInNum + "(내부 클래스의 스태틱 변수 사용)");
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수 사용)");
		}
		static void sTest(){  // 정적 클래스의 static 메서드			
			// 정적 클래스의 static 메서드에서는 내부 클래스의 인스턴스 변수도 사용할 수 없음 (외부 클래스의 인스턴스 변수도 사용할 수 없음.)
			// System.out.println("InStaticClass inNum = " + iNum + "(내부 클래스의 인스턴스 변수 사용)"); 
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수 사용)");
			System.out.println("InStaticClass sInNum = " + sInNum + "(내부 클래스의 스태틱 변수 사용)");
			
		}

	}
}
public class InnerTest2 {
	public static void main(String args[]) {
		// 인스턴스 inner class와 다르게 정적 inner class는 바로 생성 가능
		OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
		sInClass.inTest();
		
		System.out.println("\n정적 내부 클래스의 스태틱 메소드 호출");
		OutClass.InStaticClass.sTest();
		// 정적 내부 클래스의 static 메소드는 바로 호출 가능하다.

	}
}

Local Inner Class

  • 지역 변수와 같이 메서드 내부에서 정의하여 사용하는 클래스이다.

  • 지역변수와 메서드의 매개변수는 내부클래스에게는 상수로 잡혀서 읽기만 가능하고 변경은 불가하다. (final로 선언되어 사용된다.)

  • 내부 class의 method는 일을 수행하고나면 사라지는데 외부의 지역변수와 매게변수는 계속 stack에 남아있어서 변경이 불가하다.

👨🏻‍💻 Example Code1

package ch02;

class Outer {
	int outNum = 100;
	static int sNum = 200;
	
	Runnable getRunnable(int i) {
		// 매개변수 i는 매서드가 호출될 때 stack memory에 생성이 된다.
		int num = 10;
		
		class MyRunnable implements Runnable {
			
			int localNum = 1000;	
			
			@Override
			public void run() {
				//num = 200;
				//i = 100;
				// 지역변수와 메서드의 매개변수는 내부클래스에게는 상수로 잡혀서 읽기만 가능하고 변경은 불가하다. (final로 잡힘)
				// 내부 class의 method는 일을 수행하고나면 사라지는데 외부의 지역변수와 매게변수는 계속 stack에 남아있어서 변경이 불가하다. 
				
				System.out.println("i =" + i); 
				System.out.println("num = " +num);  
				System.out.println("localNum = " +localNum);
					
				System.out.println("outNum = " + outNum + "(외부 클래스 인스턴스 변수)");
				System.out.println("Outter.sNum = " + Outer.sNum + "(외부 클래스 정적 변수)");

			}
			
		}
		return new MyRunnable();
	}
}

public class LocalInnerClass {
	public static void main(String args[]) {
		Outer out = new Outer();
		Runnable runner = out.getRunnable(10);
		runner.run();
	}
}

Anonymous Inner Class (익명 내부 클래스)

  • 이름이 없는 내부 클래스로 클래스의 이름을 생략하고 주로 하나의 인터페이스나 하나의 추상 클래스를 구현하여 반환한다.

  • 인터페이스나 추상 클래스 자료형의 변수에 직접 대입하여 클래스를 생성하거나 지역 내부 클래스의 메서드 내부에서 생성하여 반환할 수 있다.

  • Android programming의 widget 이벤트 핸들러에 활용된다.

👨🏻‍💻 Example Code1

package ch02_1;

class Outer {
	int outNum = 100;
	static int sNum = 200;
	
	Runnable getRunnable(int i) {
		// 매개변수 i는 매서드가 호출될 때 stack memory에 생성이 된다.
		int num = 10;
		
		// anonymous inner class
		return new Runnable() {
			
			int localNum = 1000;	
			
			@Override
			public void run() {
				//num = 200;
				//i = 100;
				// 지역변수와 메서드의 매개변수는 내부클래스에게는 상수로 잡혀서 읽기만 가능하고 변경은 불가하다. (final로 잡힘)
				// 내부 class의 method는 일을 수행하고나면 사라지는데 외부의 지역변수와 매게변수는 계속 stack에 남아있어서 변경이 불가하다. 
				
				System.out.println("i =" + i); 
				System.out.println("num = " +num);  
				System.out.println("localNum = " +localNum);
					
				System.out.println("outNum = " + outNum + "(외부 클래스 인스턴스 변수)");
				System.out.println("Outter.sNum = " + Outer.sNum + "(외부 클래스 정적 변수)");

			}
			
		};
	}
	/* 다음과 같이도 사용 가능
	Runnable runnable = new Runnable() {
		@Override
		public void run() {
			
		}
	};
	*/
}

public class AnonymousInnerTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Outer out = new Outer();
		Runnable runner = out.getRunnable(10);
		runner.run();
	}

}



Reference

profile
블로그 이전했습니다. -> https://seongwon.dev/

0개의 댓글