ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 24. 내부클래스
    개발자 수업/Java 2021. 10. 19. 15:29

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

     

     

    2. 인스턴스 내부 클래스
        1) 내부적으로 사용할 클래스를 선언(private 선언하는 것을 권장)
        2) 외부 클래스가 생성된 후 생성됨(정적 내부 클래스와는 다름)
        3) private이 아닌 내부 클래스는 다른 외부 클래스에서 생성할 수 있음
        4) 내부 클래스의 객체 생성
           외부클래스.내부클래스 참조변수 = 외부클래스의 객체변수.new 내부클래스 생성자();

    class OuterClass {
    	private int num = 10;
    	private static int sNum = 20;
    	private InClass inClass;
    	
    	public OuterClass() {
    		inClass = new InClass();
    	}
    	
    	private class InClass {
    		int iNum = 100;
    		// static int sInNum = 500; static은 멤버로 가질 수 없음
    		void inTest() {
    			System.out.println("OuterClass num = " + num + ": 외부 클래스의 인스턴스 변수");
    			System.out.println("OuterClass sNum = " + sNum + " : 외부 클래스의 static(클래스) 변수");
    			System.out.println("InClass iNum = " + iNum + " : 내부 클래스의 인스턴스 변수");
    		}
    	}
    	
    	public void usingClass() {
    		inClass.inTest();
    	}
    }
    
    public class InnerTest {
    	public static void main(String[] args) {
    		OuterClass outerClass = new OuterClass();
    		outerClass.usingClass();
    		System.out.println();
    		
    //		OuterClass.InClass inner = outerClass.new InClass();
    //		inner.inTest(); 내부 클래스에 private이 있어서 불가능
    	
    	}
    }



    3. 정적(static) 내부 클래스
        1) 외부클래스 생성과 무관하게 사용할 수 있음
        2) 정적 변수, 정적 메서드 사용
        3) 내부 클래스의 객체 생성
           외부클래스.정적내부클래스 참조변수 = new 외부클래스.정적내부클래스생성자();

    class OuterClass {
    	private int num = 10;
    	private static int sNum = 20;
    	private InClass inClass;
    	
    	public OuterClass() {
    		inClass = new InClass();
    	}
    	
    	private class InClass {
    		int iNum = 100;
    		// static int sInNum = 500; static은 멤버로 가질 수 없음
    		void inTest() {
    			System.out.println("OuterClass num = " + num + ": 외부 클래스의 인스턴스 변수");
    			System.out.println("OuterClass sNum = " + sNum + " : 외부 클래스의 static(클래스) 변수");
    			System.out.println("InClass iNum = " + iNum + " : 내부 클래스의 인스턴스 변수");
    		}
    	}
    	
    	public void usingClass() {
    		inClass.inTest();
    	}
    	
    	// 정적 내부 클래스
    	static class InStaticClass{
    		int iNum = 100;
    		static int sInNum = 200;
    		
    		// 정적 클래스의 일반메서드
    		void inTest() {
    			// 외부 클래스의 인스턴스 변수는 정적 내부 클래스에서 사용할 수 없음
    			// System.out.println("OuterClass num = " + num + ": 외부 클래스의 인스턴스 변수"); 
    			System.out.println("OuterClass sNum = " + sNum + " : 외부 클래스의 static(클래스) 변수");
    			System.out.println("InClass iNum = " + iNum + " : 내부 클래스의 인스턴스 변수");
    			System.out.println("InStaticClass sInNum = " + sInNum + " : 내부 클래스의 static 변수");
    		}
    		
    		// 정적 클래스의 static메서드
    		static void sTest() {
    			// System.out.println("OuterClass num = " + num + ": 외부 클래스의 인스턴스 변수"); 
    			System.out.println("OuterClass sNum = " + sNum + " : 외부 클래스의 static(클래스) 변수");
    			// System.out.println("InClass iNum = " + iNum + " : 내부 클래스의 인스턴스 변수");
    			System.out.println("InStaticClass sInNum = " + sInNum + " : 내부 클래스의 static 변수");
    		}
    	}
    }
    
    public class InnerTest {
    	public static void main(String[] args) {
    		OuterClass outerClass = new OuterClass();
    		outerClass.usingClass();
    		System.out.println();
    		
    //		OuterClass.InClass inner = outerClass.new InClass();
    //		inner.inTest(); 내부 클래스에 private이 있어서 불가능
    		
    		// 외부클래스 생성하지 않고 바로 정적내부클래스 생성
    		OuterClass.InStaticClass sInClass = new OuterClass.InStaticClass();
    		sInClass.inTest();
    		System.out.println();
    		
    		// 정적 내부 클래스의 static 메서드 호출(sTest())
    		OuterClass.InStaticClass.sTest();
    	}
    }



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

    package kr.co.ezenac.localinnerclass;
    
    class Outer {
    	int outNum = 100;
    	static int sNum = 200;
    	
    	Runnable getRunnable(int i) {			// final
    		int num = 100;						// final
    		
    		class MyRunnable implements Runnable {
    			
    			int localNum = 10;				// final
    			
    			@Override
    			public void run() {
    				// num = 200;	getRunnable() 메서드 호출이 끝나면 메서드에 사용된 지역변수의 유효성이 사라지기 때문에 호출할 수 없음
    				
    				// 메서드 호출 이후에도 사용해야 하는 경우가 있으므로
    				// 지역 내부 클래스에서 사용하는 메서드의 지역변수나 매개변수는 final로 선언됨
    				System.out.println("num = " + num);
    				
    				// i = 100;
    				System.out.println("i = " + i);
    				
    				System.out.println("localNum = " + localNum);
    				System.out.println("outNum = " + outNum);	// 외부클래스의 인스턴스 변수
    				System.out.println("sNum = " + Outer.sNum);		// 외부클래스의 정적 변수 (Outer. 생략 가능)
    			}
    		}
    		
    		return new MyRunnable();
    	}
    }
    
    public class LocalinnerTest {
    	public static void main(String[] args) {
    		
    		Outer outer = new Outer();
    		
    		// MyRunnable 클래스 사용하려면 직접 생성하는 것이 아니고
    		// gerRunnable() 메서드를 호출하여 생성된 객체를 반환받아야 함
    		Runnable runnable = outer.getRunnable(10);	// 메서드 호출이 끝나면 메서드에 사용된 지역변수의 유효성 사라짐
    		runnable.run();
    	}
    }



    5. 익명(anonymous) 내부 클래스
        1) 이름이 없는 클래스
        2) 클래스의 이름을 생략하고 주로 하나의 인터페이스나 하나의 추상클래스를 구현하여 반환
        3) 인터페이스나 추상 클래스 자료형의 변수에 직접 대입하여 클래스 생성하거나 
           지역 내부 클래스의 메서드 내부에 생성하여 반환할 수 있음
        4) 이벤트 핸들러에 활용됨

    package kr.co.ezenac.anonymousinnerclass;
    
    class Outer {
    	int outNum = 100;
    	static int sNum = 200;
    	
    	Runnable getRunnable(int i) {		// final
    		int num = 100;					// final
    		
    		return new Runnable() {			// 익명 내부 클래스1
    			
    			int localNum = 10;			// final
    			
    			@Override
    			public void run() {
    				// num = 200;	getRunnable() 메서드 호출이 끝나면 메서드에 사용된 지역변수의 유효성이 사라지기 때문에 호출할 수 없음
    				
    				// 메서드 호출 이후에도 사용해야 하는 경우가 있으므로
    				// 지역 내부 클래스에서 사용하는 메서드의 지역변수나 매개변수는 final로 선언됨
    				System.out.println("num = " + num);
    				
    				// i = 100;
    				System.out.println("i = " + i);
    				
    				System.out.println("localNum = " + localNum);
    				System.out.println("outNum = " + outNum);	// 외부클래스의 인스턴스 변수
    				System.out.println("sNum = " + Outer.sNum);		// 외부클래스의 정적 변수 (Outer. 생략 가능)
    			}
    		};
    		
    	}
    	
    	// 익명 내부 클래스2
    	Runnable runnable = new Runnable() {
    		
    		@Override
    		public void run() {
    			System.out.println("Runnable이 구현된 익명 클래스 변수");
    			
    		}
    	};
    }
    
    public class LocalinnerTest {
    	public static void main(String[] args) {
    		
    		Outer outer = new Outer();
    		
    		// MyRunnable 클래스 사용하려면 직접 생성하는 것이 아니고
    		// gerRunnable() 메서드를 호출하여 생성된 객체를 반환받아야 함
    		Runnable runnable = outer.getRunnable(10);	// 메서드 호출이 끝나면 메서드에 사용된 지역변수의 유효성 사라짐
    		runnable.run();
    		System.out.println();
    		
    		outer.runnable.run();
    	}
    }

    '개발자 수업 > Java' 카테고리의 다른 글

    26. 스트림  (0) 2021.10.19
    25. 람다식  (0) 2021.10.19
    23. UML  (0) 2021.10.18
    22. Review  (0) 2021.10.18
    21. 컬렉션 프레임워크  (0) 2021.10.14

    댓글