내부 클래스

내부클래스는 클래스안에 클래스를 말한다. 내부클래스는 외부 클래스의 인스턴스가 생성되야만 접근이 가능하다. (static이 아닌경우)


내부클래스 예제

package innerclass;


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

    private InClass inClass;


    public OutClass() {
        inClass = new InClass();
    }

    class InClass {
        int inNum = 100;

        void inTest() {
            System.out.println("OutClass num =" + num + "(외부 클래스의 인스턴스 변수)");
            System.out.println("OutClass num =" + sNum + "(외부 클래스의 인스턴스 변수)");
        }
    }    

    public void usingClass() {
        inClass.inTest();
    }    
}


public class innerTest {
    public static void main(String[] args) {
        OutClass outClass = new OutClass();
        System.out.println("외부 클래스 이용하여 내부 클래스 기능 호출");
        outClass.usingClass();
    }
}

  • 외부클래스 인스턴스를 생성해야 내부클래스를 사용할 수 있다.
  • 내부클래스에서 외부 클래스의 인스턴스 변수에 접근이 가능하다.
  • 내부클래스에는 static 변수나 메서드를 사용할 수 없다.
  • 인스턴스 내부에 있는 클래스는 외부 클래스의 메서드가 호출 될 때 사용할 수 있다.
        OutClass.InClass inClass = outClass.new InClass();
        System.out.println("외부 클래스 변수를 이용하여 내부 클래스 생성");
        inClass.inTest();
  • 위와 같은 방법으로 인스턴스 내부에 있는 클래스를 생성할 수 있음.

정적 내부 클래스

내부클래스를 static으로 선언하여 내부 변수와 메서드도 static 으로 접근 가능.

정적 내부클래스 선언 예제

package innerclass;


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 // <---- 에러!


        void inTest() {
            System.out.println("OutClass num =" + num + "(외부 클래스의 인스턴스 변수)");
            System.out.println("OutClass num =" + sNum + "(외부 클래스의 인스턴스 변수)");
        }
    }    

    public void usingClass() {
        inClass.inTest();
    }    


    static class InStaticClass {
        int inNum = 100;
        static int sInNum = 200;

        void inTest() {
            System.out.println("InStaticClass inNum =" + inNum + "(내부 클래스의 인스턴스 변수 사용)");
            System.out.println("InStaticClass sInNum =" + sInNum + "(내부 클래스의 스태틱 변수 사용)");
            System.out.println("InStaticClass inNum =" + sNum + "(외부 클래스의 스태틱 변수 사용)");
        }

        static void sTest() {
            System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수 사용)");
            System.out.println("InStaticClass sInNum = " + sInNum + "(내부 클래스의 스태틱 변수 사용)");
        }

    }


//    public int getInNum() {
//        return inClass.inNum;
//    }

}


public class innerTest {
    public static void main(String[] args) {
        OutClass outClass = new OutClass();
        System.out.println("외부 클래스 이용하여 내부 클래스 기능 호출");
        outClass.usingClass();

        System.out.println();

        OutClass.InClass inClass = outClass.new InClass();
        System.out.println("외부 클래스 변수를 이용하여 내부 클래스 생성");
        inClass.inTest();

        System.out.println();

        OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
        System.out.println("정적 내부 클래스 일반 메서드 호출");
        sInClass.inTest();
        System.out.println();

        System.out.println("정적 내부 클래스의 스태틱 메소드 호출");
        OutClass.InStaticClass.sTest();


    }
}
  • 정적 내부클래스는 외부 인스턴스를 생성하지 않고 바로 생성할 수 있다. new OutClass.InStaticClass();
  • 인스턴스 변수와 스태틱변수 & 메서드에 대해 유효범위가 다르므로, 주의가 필요하다.


지역내부클래스

메서드안에서 사용하는 클래스

LocalInnerTest.java

package innerclass;

class Outer {
    int outNum = 100;
    static int sNum = 200;

    Runnable getRunnable(int i) {
        int num = 100;

        class MyRunnable implements Runnable {
            int localNum = 10;
            @Override
            public void run() {
                System.out.println("i=" + i);  // 10
                System.out.println("num=" + num); // 100
                System.out.println("localNum=" + localNum); // 10

                System.out.println("outNum=" + outNum + "(외부 클래스 인스턴스 변수)"); // 100
                System.out.println("Outter.sNum=" + Outer.sNum + "(외부 클래스 정적 변수)"); // 200
            }
        }

        return new MyRunnable();

    }

}


public class LocalInnerTest {

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

}
  • 지역내부클래스에서 사용하는 지역변수는 모두 컴파일 과정에서 상수(final) 로 바뀐다.
  • 그래서 getRunnable 메서드의 인자 i와 num 은 바꿀 수 없다.

익명내부클래스

AnonymousInnerTest.class

package innerclass;

class Outter {

    // 방법1
    Runnable getRunnable(int i) {
        int num = 100;

        return new Runnable() {
            @Override
            public void run() {
                System.out.println(i);
                System.out.println(num);
            }
        };
    }


    // 방법2
    Runnable runner = new Runnable() {
        @Override
        public void run() {
            System.out.println("Runnable이 구현된 익명 클래스 변수");
        }
    };


}


public class AnonymousInnerTest {

    public static void main(String[] args) {
        Outter out = new Outter();

        Runnable runnerble = out.getRunnable(10);
        runnerble.run();

        out.runner.run();

    }

}
  • 지역내부클래스와 같은 기능을 익명내부클래스로 선언하였음.

출처: do it 자바프로그래밍

'프로그래밍 > Java' 카테고리의 다른 글

스트림  (0) 2019.12.27
람다식  (0) 2019.12.25
Map  (0) 2019.12.20
싱글톤  (0) 2019.12.18
Set  (0) 2019.12.17
블로그 이미지

파니동

,