KIC/JAVA

day21 - JAVA (inner class, static 내부 클래스, non-static 내부 클래스, 지역 내부 클래스, 무명 클래스)

바차 2021. 7. 17. 00:57
반응형

[inner class]

-> 클래스 내부에 다시 클래스를 선언해야 하는 경우가 있다.

 

-> 이렇겍 클래스 내부에 들어 있는 클래스를 내부 클래스라고 한다.

 

-> 내부 클래스(중첩 클래스: nested class)는 바깥 클래스(Outer class)의 다른 멤버(메소드, 멤버변수를 말함) 와 같은 클래스의 멤버가 된다.

 

-> 내부 클래스는 다른 클래스 멤버와 마찬가지로 접근 속성을 가질 수도 있으며, 바깥 클래스 외부에서의 접근가능 여부는 접근 제어자에 의해 결정된다.

 

 

 

 

 

 

 

[static 내부  클래스]

-> static 내부 클래스(static inner class)는 내부 클래스의 객체를 바깥 클래스에 대해 독립적으로 만들 때 사용

 

-> static 키워드를 가진 내부 클래스로, 멤버 변수나 메소드처럼 클래스 내부에서 선언

 

 

-> 다른 클래스에서 Outer 클래스 내부의 클래스인 inner 클래스에 접근하기 위해서 객체를 생성할 때 다음과 같이 객체를 생성한다.

 

-> 클래스 이름 다음에 바로 inner 클래스 이름 사용

 

 

 

 

 

 

 

 

[non-static 내부  클래스]

-> non-static 내부  클래스는 static 내부 클래스와 선언되는 위치는 같으나 static 선언되지 않은 내부클래스 이다.

 

-> 다른 클래스에서 Outer 클래스의 내부클래스인 Inner 클래스에 접근하기 위해서 객체를 생성할 때는 먼저 바깥 클래스의 객체를 생성해서 그 레퍼런스를 가지고 내부 클래스의 객체를 생성한다.

 

 

 

 

 

 

 

 

[지역 내부  클래스(local inner class)]

-> static 과 non-static 내부 클래스가 바깥 클래스의 멤버의 위치에 선언되는 것에 비해, 지역 내부 클래스는 바깥 클래스의 메소드 안에 선언된 내부클래스이다.

 

 

 

 

 

 

[무명  클래스(anonymous inner class)]

-> 무명 내부 클래스는 지역 내부클래스의 변형으로 클래스 명을 갖지 않고 한번만 사용할 수 있다.

 

-> 주로 이벤트 처리에 많이 사용된다.

 

 

 

 

 

 

 

 

 

[내부 클래스 ex]

package javaPro.java_inner;
/*
 * 내부 클래스 예제
 * 
 *  인스턴스 내부클래스 :  (static)클래스 멤버를 가질 수 없다. 단 상수는 가능 
 *  static 내부클래스 : (static)클래스 멤버를 가질 수 있다.
 *  지역내부클래스        : 메서드 내에 선언된 클래스. 메서드 내부에서만 사용이 가능함.
 *  이름없는(무명의)내부클래스 : 클래스 없이 객체화 가능한 클래스
 *                        추상클래스,인터페이스 의 객체화 가능함.
 *                        
                 
 */
class Outer1 {
    class instanceInner {// 인스턴스 내부 클래스
        int iv = 100;
        //static int cv = 10; // 클래스 멤버를 가질 수 없다.
        final static int MAX = 200;
    }
    static class StaticInner { //static 내부 클래스
        int iv = 300;
        static int cv = 400;
        final static int MAX = 500;
    }

    void method(){ // 지역 내부 클래스
        class LocalInner{
            int iv = 600;
            //static int cv = 700; //클래스 멤버를 가질 수 없다.
            final static int MAX = 700; // 상수는 가능하다.
        }
        LocalInner lc = new LocalInner();
        System.out.println(lc.iv); // 600
        System.out.println(lc.MAX); // 700
        System.out.println(LocalInner.MAX); // 700
    }
    void method2(){
        //LocalInner lc = new LocalInner(); // -> method() 메서드에서만 사용가능하다.
    }
}

public class InnerEx1 {
    public static void main(String[] args) {
        Outer1.StaticInner si = new Outer1.StaticInner();
        System.out.println(si.iv); //300
        System.out.println(Outer1.StaticInner.cv); // 400
        System.out.println(Outer1.StaticInner.MAX); // 500
        //Outer1.InstanceInner ii = new Outer1.InstanceInner();
        Outer1 outer = new Outer1();
        Outer1.instanceInner ii2 = outer.new instanceInner();
        System.out.println(ii2.iv); // 100
        System.out.println(Outer1.instanceInner.MAX);
        outer.method();
    }
}

 

 

 

[지역 내부 클래스 주의해야 할 점]

-> 지역 내부 클래스에서 사용되는 메서드의 지역변수는 상수화(final) 되어야 한다.

 

-> 즉, 로컬 변수인데 final이 아닌 지역 변수는 내부 클래스에 있는 메서드 내에서 사용할 수 없다.

package javaPro.java_inner;

//[지역 내부클래스에서 사용되는 메서드의 지역변수는 상수화(final) 되어야 한다.]

class Outer2 {
    private static int outercv = 20;  //outercv 선언

    static StaticInner cv = new StaticInner();

    static InstanceInner cv2 = new Outer2().new InstanceInner(); 
    // cv2의 타입은 InstantceInner, outer2 객체 생성후 InstantceInner 메모리 할당


    static class StaticInner {              // static inner class
        int siv = new Outer2().outeriv;
        static int scv = outercv;
    
    }

    static StaticInner cv3 = new StaticInner();  // static inner 클래스도 이렇게 선언해서 사용 가능

    InstanceInner iv = new InstanceInner();
    private int outeriv = 10; // outeriv 선언

    class InstanceInner {
        int iiv = outeriv;
        int iiv2 = outercv;
    }

    void method(int pv) {
        //지역 내부클래스에서 사용되는 메서드의 지역변수는 상수화(final) 되어야 한다.
        int i = 0; // 이 i 처럼 메소드 안의 지역변수는 지역 내부클래스에서 사용되려면 final 이어야 한다.


        //pv++; // 이 코드를 실행하면 아래 print 문에서 오류가 난다.(final 은 한번 초기화 하고 수정이 불가능)
        //i++;  // 이 코드를 실행하면 아래 print 문에서 오류가 난다.(final 은 한번 초기화 하고 수정이 불가능)
        // -> 이 변수들을 수정시켰을 때 시스템 내에서 이 변수는 final이 아니라고 판단하게 되기 때문


        outeriv++; // 이건 가능


        class LocalInner { // 지역 내부 클래스
            int liv = outeriv; // 외부 클래스의 private 멤버 접근 가능
            int liv2 = outercv; // 외부 클래스의 private 멤버 접근 가능
            
            void method() {
                //지역 내부 클래스에서 내부 클래스가 속한 메서드의 지역변수 변경 안됨
                // i = 100;
                //pv++;

                System.out.println("i=" + i);
                System.out.println("pv=" + pv);
                System.out.println(liv + ", " + liv2);
                System.out.println(outeriv + ", " + outercv); // 외부클래스의 private 멤버 접근 가능
            }

        }
        LocalInner li = new LocalInner();
        li.method();

    }

}


public class InnerEx2 {
    public static void main(String[] args) {
        Outer2 out = new Outer2();
        out.method(1);

        Outer2.InstanceInner i2 = out.new InstanceInner();
        System.out.println(i2.iiv);
        System.out.println(i2.iiv2);

        //Outer2.StaticInner i3 = new Outer2().StaticInner();
        //System.out.println(i3.siv);
        System.out.println(Outer2.StaticInner.scv);
    }
}
300x250