1일1배움/Java

23/02/09 [내부클래스?]

kim chan jin 2023. 2. 9. 11:12

내부클래스의 종류는 변수의 선언위치에 따른 종류와 같다.

https://cjkimhello97.tistory.com/60

 

23/02/09 [인스턴스변수? 클래스변수? 지역변수?]

인스턴스변수, 클래스변수, 지역변수? 인스턴스변수 인스턴스가 생성될 때 생성된다. 인스턴스변수의 값으르 읽거나 저장하려면 생성자를 사용하여 인스턴스를 생성해야 한다. 인스턴스별로

cjkimhello97.tistory.com

내부클래스 특징
인스턴스클래스 외부 클래스의 멤버변수 선언위치에 선언하며 외부 클래스의 인스턴스멤버처럼 다뤄진다.
주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적으로 선언된다.
스태틱클래스 외부 클래스의 멤버변수 선언위치에 선언하며 외부 클래스의 클래스멤버(static멤버)처럼 다뤄진다.
주로 외부 클래스의 클래스멤버(static멤버), 특히 static 메서드에서 사용될 목적으로 선언된다.
지역클래스 외부 클래스의 메서드나 초기화블럭 안에 선언하며 선언된 영역 내부에서만 사용될 수 있다.
익명클래스 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용)

 

 

내부인스턴스클래스에는 클래스멤버(클래스변수) 선언 불가
내부스태틱클래스에서 클래스멤버(클래스변수) 선언 가능
내부지역클래스에는 클래스멤버(클래스변수) 선언 불가

public class Test{
    class InnerInstanceClass{ // 내부인스턴스클래스
        int iv = 100;
        // static int cv = 100; // 에러. 내부인스턴스클래스에는 클래스멤버(클래스변수) 선언불가
        final static int CONST = 100; // final static은 상수이므로 내부인스턴스클래스에서 선언가능
    }

    static class InnerStaticClass{ // 내부스태틱클래스
        int iv = 200;
        static int cv = 200; // 내부스태틱클래스에서 클래스멤버(클래스변수) 선언가능
    }

    void myMethod(){
        class InnerLocalClass{ // 내부지역클래스
            int iv = 300;
            // static int cv = 300; // 에러. 내부지역클래스에는 클래스멤버(클래스변수) 선언불가
            final static int CONST = 300; // final static은 상수이므로 내부지역클래스에서 선언가능
        }
    }

    public static void main(String[] args) {
        System.out.println(InnerInstanceClass.CONST); // 100
        System.out.println(InnerStaticClass.cv); // 200
    }
}

 

 

 

 


 

 

 

 

 내부지역클래스는 메서드 또는 초기화블럭 내에서 일회용

public class Test{
    class InnerInstanceClass{ // 내부인스턴스클래스
        int iv = 100;
        // static int cv = 100; // 에러. 내부인스턴스클래스에는 클래스멤버(클래스변수) 선언불가
        final static int CONST = 100; // final static은 상수이므로 내부인스턴스클래스에서 선언가능
    }

    static class InnerStaticClass{ // 내부스태틱클래스
        int iv = 200;
        static int cv = 200; // 내부스태틱클래스에서 클래스멤버 선언가능
    }

    void myMethod(){
        class InnerLocalClass{ // 내부지역클래스
            int iv = 300;
            // static int cv = 300; // 에러. 내부지역클래스에는 클래스멤버(클래스변수) 선언불가
            final static int CONST = 300; // final static은 상수이므로 내부지역클래스에서 선언가능
        }
    }


    void instanceMethod(){
        InnerInstanceClass iic = new InnerInstanceClass();

        InnerStaticClass isc = new InnerStaticClass();

        // InnerLocalClass ilc = new InnerLocalClass(); // 에러. 내부지역클래스는 메서드 또는 초기화블럭 내에서 일회용임

    }

    static void staticMethod(){
        // InnerInstanceClass iic = new InnerInstanceClass(); // 에러. 클래스멤버(static메서드)는 인스턴스멤버에 접근 불가
        // 굳이 접근하려면 아래와 같이 인스턴스 생성해야 함
        Test outerClass = new Test(); // 외부클래스 인스턴스를 먼저 생성한 이후에
        InnerInstanceClass iic = outerClass.new InnerInstanceClass(); // 내부인스턴스클래스 인스턴스를 생성할 수 있다.

        InnerStaticClass isc = new InnerStaticClass();

        // InnerLocalClass ilc = new InnerLocalClass(); // 에러. 내부지역클래스는 메서드 또는 초기화블럭 내에서 일회용임
    }
}

 

 

 

 

 

 


 

 

 

 

 

내부지역클래스에서 외부클래스의 인스턴스변수 접근가능
내부지역클래스에서 외부클래스의 스태틱변수 접근가능
내부지역클래스에서 외부클래스의 지역변수 접근가능(JDK1.8부터 가능)
내부지역클래스에서 외부클래스의 final지역변수 접근가능

public class Test{ // 외부클래스
    private int outerIv = 0;
    static int outerCv = 0;

    class InnerInstanceClass{ // 내부인스턴스클래스
        int iiv1 = outerIv; // 외부클래스의 private멤버 접근가능
        int iiv2 = outerCv;
    }

    static class InnerStaticClass{ // 내부스태틱클래스
        // int siv = outerIv; // 에러. 내부스태틱클래스에서 외부클래스의 인스턴스변수 접근불가능
        static int scv = outerCv;
    }

    void myMethod(){
        int lv = 0;
        final int LV = 0; // JDK1.8부터 final 생략가능. 컴파일러가 자동으로 붙여줌

        class InnerLocalClass{ // 내부지역클래스
            int liv1 = outerIv; // 외부클래스의 인스턴스변수 접근가능
            int liv2 = outerCv; // 외부클래스의 스태틱변수 접근가능
            int liv3 = lv; // 외부클래스의 지역변수 접근가능(JDK1.8부터 가능)
            int liv4 = LV; // 외부클래스의 지역변수 접근가능(final이므로)
        }
    }
}

 

 

 

 

 


 

 

 

 

 

내부인스턴스클래스의 인스턴스를 생성하기 위해선 외부클래스의 인스턴스부터 먼저 생성해야 한다.
내부스태틱클래스의 클래스변수(cv)는 인스턴스 생성할 필요없이 "외부클래스.내부스태틱클래스.멤버변수"로 접근가능  
내부스태틱클래스의 인스턴스변수(iv)에 접근하기 위해서 내부스태틱클래스의 인스턴스를 생성해야 한다.

class OuterClass{ // 외부클래스
    class InnerInstanceClass{ // 내부인스턴스클래스
        int iv = 100;
    }

    static class InnerStaticClass{ // 내부스태틱클래스
        int iv = 200;
        static int cv = 300;
    }

    void myMethod(){
        class InnerLocalClass{ // 내부지역클래스
            int iv = 400;
        }
    }
}

public class Test{
    public static void main(String[] args) {
        // 내부인스턴스클래스의 인스턴스를 생성하기 위해선
        OuterClass oc = new OuterClass(); // 먼저 외부클래스의 인스턴스를 생성한 후에
        OuterClass.InnerInstanceClass ii = oc.new InnerInstanceClass(); // 내부인스턴스클래스 인스턴스를 생성해야 한다.
        System.out.println("ii.iv: " + ii.iv); // 내부인스턴스클래스의 인스턴스(ii)의 멤버변수(iv)

        System.out.println("OuterClass.InnerStaticClass.cv: " + OuterClass.InnerStaticClass.cv);
        // 내부스태틱클래스의 클래스변수(cv)는 인스턴스 생성할 필요없이 "외부클래스.내부스태틱클래스.멤버변수"로 접근가능

        OuterClass.InnerStaticClass si = new OuterClass.InnerStaticClass();
        // 내부스태틱클래스의 인스턴스변수(iv)에 접근하기 위해서 내부스태틱클래스의 인스턴스를 생성해야 한다.
        // 외부클래스.내부스태틱클래스 참조변수 = new 외부클래스.내부스태틱클래스생성자
        System.out.println("si.iv: " + si.iv);
    }
}

 

 

 

 

 


 

 

 

 

 

익명클래스는 클래스의 선언과 객체의 생성을 동시에 하는 방식이다.
내부인스턴스클래스를 익명클래스로 할 수도 있다. (클래스가 보이지 않을 뿐)
내부스태틱클래스를 익명클래스로 할 수도 있다. (클래스가 보이지 않을 뿐)
내부지역클래스를 익명클래스로 할 수도 있다. (클래스가 보이지 않을 뿐)

public class Test{
    Object anonymous1 = new Object(){void method(){}}; // 내부인스턴스클래스를 익명클래스로
    static Object anonymous2 = new Object(){void method(){}}; // 내부스태틱클래스를 익명클래스로
    
    void myMethod(){
        Object anonymous3 = new Object(){void method(){}}; // 내부지역클래스를 익명클래스로
    }
}

 

 

 

 

 


 

 

 

 

참조변수 없이 익명클래스를 사용할 수 있다.

import java.awt.*;
import java.awt.event.*;

public class Test{
    public static void main(String[] args) {
        Button b = new Button("Start");
        b.addActionListener(new ActionListener() { // 참조변수 없이 익명클래스 사용
            public void actionPerformed(ActionEvent e){
                System.out.println("ActionEvent occured!!!");
            }
        });
    }    
}