[Java]내부클래스 유형(feat. 람다식 변환)

JANG SEONG SU·2023년 7월 26일

Java

목록 보기
7/10
post-thumbnail

내부클래스(Inner class)란?

aka. 중첩 클래스
종류 : 인스턴스 내부 클래스, 정적(static) 내부 클래스, 지역(local) 내부 클래스, 익명(anonymous) 내부 클래스

인스턴스 내부클래스

// 외부 클래스를 이용하여 내부 클래스 생성
OutClass outClass = new OutClass();
OutClass.InClass inClass = outClass.new InClass();
class OutClass {

	private int num = 10;
	private static int sNum = 20;
	private InClass inClass;
	
	public OutClass(){
		inClass = new InClass(); // 내부 클래스 생성
	}
	
	class InClass{
    
		int inNum = 100;
		//static int sInNum = 200;  //에러 남
        //static void sTest(){  //에러 남
	    	
	    //}	//인스턴스 내부클래스에서는 정적변수,함수 선언 불가
		
		void inTest(){
			System.out.println("OutClass num = " +num + "(외부 클래스의 인스턴스 변수)");
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수)");
			System.out.println("InClass inNum = " + inNum + "(내부 클래스의 인스턴스 변수)");
		}
	}
	
	public void usingClass(){
		inClass.inTest(); //외부 클래스에서 내부 클래스 변수를 사용하여 메서드 호출하기
	}
}

정적 내부클래스

//외부 클래스 생성하지 않고 바로 정적 내부 클래스 생성
OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
class OutClass {

	private int num = 10;
	private static int sNum = 20;
	private InClass inClass;
	
	public OutClass(){
		inClass = new InClass(); // 내부 클래스 생성
	}

	static class InStaticClass{
		
		int inNum = 100;
		static int sInNum = 200;
		
		void inTest(){   //정적 클래스의 일반 메서드
			//num += 10;    // 외부 클래스의 인스턴스 변수는 사용할 수 없음.
			System.out.println("InStaticClass inNum = " + inNum + "(내부 클래스의 인스턴스 변수 사용)"); 
			System.out.println("InStaticClass sInNum = " + sInNum + "(내부 클래스의 스태틱 변수 사용)");
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수 사용)");
		}
		
		static void sTest(){  // 정적 클래스의 static 메서드
			//num += 10;   // 외부 클래스의 인스턴스 변수는 사용할 수 없음.
			//inNum += 10; // 내부 클래스의 인스턴스 변수는 사용할 수 없음
			
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수 사용)");
			System.out.println("InStaticClass sInNum = " + sInNum + "(내부 클래스의 스태틱 변수 사용)");
			
		}
	}	
}

익명 내부클래스

//외부클래스 이용하여 내부클래스 메소드 실행
Outer out = new Outer();
Runnable runner = out.getRunnable(10);
runner.run();
class Outer{
    int outNum = 100;
    static int sNum = 200;
    Runnable getRunnable(final int i){	//final 선언 해야함

        final int num = 100;		//final 선언 해야함

        class MyRunnable implements Runnable{
            int localNum = 10;

            @Override
            public void run() {
                outNum = 5;
                //num = 200;   //에러 남. 지역변수(함수 내에서 선언된 변수)는 상수로 바뀜
                //i = 100;     //에러 남. 매개 변수 역시 지역변수처럼 상수로 바뀜,
                               //num, i는 메소드가 실행되는 동안 Stack에 쌓이고, 함수 실행이 끝나면, Stack에서 해제된다.
                               //getRunnable()메소드와 MyRunnalbe의 클래스의 실행 주기가 달라서, 내구 클래스에서 stack에 할당 된 변수를 사용하면 안된다. 따라서 final 처치 해야함.
                               //즉, 사용하는 것은 OK, 변경하는 것은 안됨
                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();
    }
}

익명 내부클래스를 람다식으로

  1. 우선 익명 내부클래스를 일회성으로 아래의 코드로 나타낼 수 있다.
Outer out = new Outer();
Runnable runner = out.getRunnable(10);
        runner.run();

        Runnable runner = new Runnable(){
            int localNum = 10;

            @Override
            public void run() {
                System.out.println("localNum = " +localNum);
            }
        };
        runner.run();
  1. 위 코드를 다시 람다식으로 변환하면, 아래와 같은 코드로 나타낼 수 있다.
Runnable runner = ()->{
            int localNum = 10;
            System.out.println("localNum = " +localNum);
        };

        runner.run();

profile
Software Developer Lv.0

0개의 댓글