본문 바로가기
언어/JAVA

여러 내부 클래스

by step 1 2021. 5. 8.
반응형

내부 클래스 (inner class)

  • 클래스 내부에 선언한 클래스로 이 클래스를 감싸고 있는 외부 클래스와 밀접한 연관이 있는 경우가 많고 다른 외부 클래스에서 사용할 일이 거의 없는 경우에 내부 클래스로 선언해서 사용함
  • 중첩 클래스라고도 함
  • 내부 클래스의 종류: 인스턴스 내부클래스, 정적(static) 내부 클래스, 지역(local) 내부 클래스, 익명(anonymous) 내부 클래스

인스턴스 내부 클래스

  • 내부적으로 사용할 클래스를 선언 (private으로 선언하는 것을 권장)
  • 외부 클래스가 생성된 후 생성됨(정적 내부 클래스와 다름)
  • private이 아닌 내부 클래스는 다른 외부 클래스에서 생성할 수 있음
package ch51;

class OutClass {
	
	private int num = 0;
	private static int sNum = 20;
	private InClass inClass;
	
	public OutClass() {

		inClass = new InClass();
	}
	
	// out class 가 생성되고 생성
	class InClass {
		
		int iNum = 100;
		
		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();
	}
}
public class innerTest {

	public static void main(String[] args) {
		
		OutClass outClass = new OutClass();
		outClass.usingClass();
		
		System.out.println();
		
		OutClass.InClass inner = outClass.new InClass();
		
		inner.inTest();
	}
}

 

정적 내부 클래스

  • 외부 클래스 생성과 무관하게 사용할 수 있음
  • 정적 변수, 정적 메서드 사용
  • 정적 내부 클래스 예
package ch51;

class OutClass {
	
	private int num = 0;
	private static int sNum = 20;
	private InClass inClass;
	
	public OutClass() {

		inClass = new InClass();
	}
	
	// out class 가 생성되고 생성
	class InClass {
		
		int iNum = 100;
		
		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();
	}
	
	static class InStaticClass {
		
		int iNum = 100;
		static int sInNum = 200;
		
		void inTest() {
			
			System.out.println("InClass num = " + iNum + "(내부 클래스의 인스턴스 변수)");
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스테틱 변수)");
			System.out.println("InClass inNum = " + sInNum + "(내부 클래스의 스테틱 변수)");
		}
		
		static void sTest() {
			
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스테틱 변수)");
			System.out.println("InClass inNum = " + sInNum + "(내부 클래스의 스테틱 변수)");
		}
		
	}
}
public class innerTest {

	public static void main(String[] args) {
		
//		OutClass outClass = new OutClass();
//		outClass.usingClass();
//		
//		System.out.println();
//		
//		OutClass.InClass inner = outClass.new InClass();
//		
//		inner.inTest();
		
		// 외부 인스턴스 변수 사용 불가
		OutClass.InStaticClass sInclass = new OutClass.InStaticClass();
		sInclass.inTest();
		
		System.out.println();
		
		// 스태틱 변수들만 사용가능
		OutClass.InStaticClass.sTest();
	}
}

 

지역 내부 클래스

  • 지역 변수와 같이 메서드 내부에서 정의하여 사용하는 클래스
  • 메서드의 호출이 끝나면 메서드에 사용된 지역변수의 유효성은 사라짐
  • 메서드 호출 이후에도 사용해야 하는 경우가 있을 수 있으므로 지역 내부 클래스에서 사용하는 메서드의 지역 변수나 매개변수는 final로 선언됨
package ch51;

class Outer2{
	
	int outNum = 100;
	static int sNum = 200;
	
	Runnable getNuRunnable(int i) {
		
		int num = 10;
		
		class MyRunnable implements Runnable {

			int localNum = 100000;
			
			@Override
			public void run() {
				
				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 = " + Outer2.sNum + "(외부 클래스 정적 변수)");
			}
			
		}
		return new MyRunnable();
	}
}
public class AnonymousInnerTest {

	public static void main(String[] args) {
		
		Outer2 out = new Outer2();
		Runnable runner = out.getNuRunnable(100);
		
		runner.run();
	}
}

MyRunnable 클래스를 사용하려면 직접 생성하는 것이 아닌 getRunnable()메서드를 호출하여 생성된 개체를 반환 받아야 함

 

익명 내부 클래스

  • 이름이 없는 클래스 (위 지역 내부 클래스의 MyRunnable) 클래스 이름은 실제로 호출되는 경우가 없음
  • 클래스의 이름을 생략하고 주로 하나의 인터페이스나 하나의 추상 클래스를 구현하여 반환
  • 인터페이스나 추상 클래스 자료형의 변수에 직접 대입하여 클래스를 생성하거나 지역 내부 클래스의 메서드 내부에서 생성아여 반환 할 수 있음
  • widget의 이벤트 핸들러에 활용됨
package ch51;

class Outer2{
	
	int outNum = 100;
	static int sNum = 200;
	
	Runnable getNuRunnable(int i) {
		
		int num = 10;
		
//		class MyRunnable implements Runnable {
//
//			int localNum = 100000;
//			
//			@Override
//			public void run() {
//				
//				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 = " + Outer2.sNum + "(외부 클래스 정적 변수)");
//			}
//			
//		}
//		return new MyRunnable();
		
		// 익명 inner class로 변환
		return new Runnable() {
			
			int localNum = 1000;
			
			@Override
			public void run() {

				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 = " + Outer2.sNum + "(외부 클래스 정적 변수)");
				
			}
		};
	}
	
	// 익명 inner class(많이 사용됨)
	Runnable runnable = new Runnable() {
		
		@Override
		public void run() {

			System.out.println("Runnable calss");
		}
	};
}
public class AnonymousInnerTest {

	public static void main(String[] args) {
		
		Outer2 out = new Outer2();
		Runnable runner = out.getNuRunnable(100);
		
		runner.run();
		
		out.runnable.run();
	}
}

 

반응형

'언어 > JAVA' 카테고리의 다른 글

스트림(Stream)  (0) 2021.05.08
람다식  (0) 2021.05.08
Map 인터페이스  (0) 2021.05.02
Comparable, Comparator 인터페이스  (0) 2021.05.02
Set 인터페이스  (0) 2021.05.02