반응형

 

내부 클래스

 

내부 클래스(inner class)는 다른 클래스 내부에 선언된 클래스를 의미한다. 내부 클래스는 클래스의 멤버로 간주되며, 속해있는 클래스의 멤버 변수와 메서드에 쉽게 접근할 수 있다.

외부 클래스라는 단어가 나올 텐데 내부 클래스가 속해있는 클래스를 칭하는 단어라고 생각하면 된다.

 

내부 클래스의 종류에는 크게 네 가지가 있다.

 

멤버 내부 클래스(Member Inner Class): 외부 클래스의 멤버 변수와 메서드와 동일한 수준에서 선언된 클래스. 외부 클래스의 인스턴스에 종속적이며, 따라서 외부 클래스의 인스턴스가 생성되어야만 사용할 수 있다.

정적 내부 클래스(Static Inner Class): 내부 클래스가 정적으로 선언된 경우이다. 외부 클래스의 인스턴스와 독립적으로 동작하며, 외부 클래스의 정적 멤버에만 접근할 수 있다.

지역 내부 클래스(Local Inner Class): 메서드나 블록 내부에서 선언된 클래스이며 해당 메서드나 블록 내부에서만 사용할 수 있다.

익명 내부 클래스(Anonymous Inner Class): 이름이 없는 내부 클래스로, 인터페이스나 추상 클래스의 구현을 간단하게 표현할 때 사용

 

 

 

 


 

멤버 내부 클래스 (Member Inner Class)

 

//외부 클래스 OutClass
public class OutClass {
    private int number; //private형은 내부 클래스에서도 사용 가능하다.
    private int number2;
    private InClass innerClass; //OutClass 안의 내부 클래스 innerClass

    public OutClass(int n1, int n2) {
        this.number=n1;
        this.number2=n2;
        innerClass = new InClass(); //OutClass 생성시 InClass 생성
    }

    public int InClassUsing() {
        return innerClass.plusOperator(this.number,this.number2);
    }
    
    //=================멤버 내부 클래스====================
    public class InClass{
        int inNum=100;
        //static int num = 200; // 정적 변수&메서드 선언은 불가능하다.
        void printNum() {
            System.out.println("inner class num : "+inNum);
        }

        int plusOperator(int num, int num2) {
            return num+num2;
        }
    }

    //=================멤버 내부 클래스====================

    

    public static void main(String[] args) {
            OutClass c1 = new OutClass(10,20);
            System.out.println("내부 클래스 사용 연산 호출 : "+c1.InClassUsing());
    }

}

 

멤버 내부 클래스는 주로 외부 클래스 내부에서만 생성하여 사용하는 객체를 선언할 때 사용한다.
주로 다른 외부 클래스에서 사용할 일이 없는 경우 내부 인스터스 클래스로 정의한다.
외부 클래스를 먼저 생성하지 않고 인스턴스 내부 클래스를 사용할 수 없다.

 

 

public static void main(String[] args) {
        OutClass.InClass c2 = c1.new InClass(); 
        System.out.println("직접 내부 클래스 사용 연산  : "+c2.plusOperator(100,200));
}

 

다른 클래스에서 인스턴스 내부 클래스에 대한 인스턴스를 생성하는 것도 가능하기는 하다.
단 다른 클래스에서 내부 클래스를 사용하려면 내부 클래스가 private로 선언되어서는 안된다.

반대로 어떤 클래스의 내부에서만 사용하려면 private으로 선언하여 사용하면 된다.

 

 

 

 

 

 


정적 내부 클래스 (Static Inner Class)

 

//외부 클래스 OutClass
public class OutClass {
    private int number; //private형은 내부 클래스에서도 사용 가능하다.
    private int number2;


    //==================정적 내부 클래스=====================
    static class InStaticClass{
        static int number3=100;
        int number4=100;

        //정적 메서드
        static int staticClassInput(int num) {
            //number4++; //정적 메서드에서는 외부 클래스의 인스턴스 변수 사용 불가능. 정적 메서드에서는 내부 클래스와 외부 클래스의 정적 변수(static 변수)만 사용 가능하다.
            return num+number3;
        }

        //일반 메서드
        int ClassInput(int num) {
            return num+this.number4;	//일반 메서드에서는 외부 클래스의 인스턴스 변수는 사용 불가능하지만 정적 변수와 내부 클래스의 인스턴스 변수와 정적 변수를 사용 가능하다.
        }

    }
    //==================정적 내부 클래스=====================


    public static void main(String[] args) {
        // 정적 내부 클래스의 경우 외부 클래스를 생성하지 않고 바로 내부 클래스 생성 가능.
        OutClass.InStaticClass s1 = new OutClass.InStaticClass();
        System.out.println("정적 내부 클래스(정적 메서드) 사용 : "+s1.staticClassInput(10));
        System.out.println("정적 내부 클래스 사용(일반 메서드) : "+s1.ClassInput(10));

    }


}


정적 내부 클래스는 외부 클래스 생성과 무관하게 사용할 수 있어야 하고 정적 변수를 사용할 수 있게 하려면 사용한다.

위의 코드와 같이 외부 클래스를 생성하지 않고 바로 내부 클래스의 인스턴스를 생성할 수 있다.
해당 인스턴스는 정적 내부 클래스의 정적 메서드와 일반 메서드 두개 모두 사용 가능하다.       

 

 

 

 

 

 


지역 내부 클래스(Local Inner Class)

 

public class OutClass {
    private int number; 
    private int number2;

    public OutClass(int n1, int n2) {
        this.number=n1;
        this.number2=n2;
    }

    //==================지역 내부 클래스=====================
    public double localClassTest() {
        int num=100; //지역변수

        //지역 내부 클래스 Point
        class Point{
            double x;
            double y;
            Point(double x, double y){
                this.x=x;
                this.y=y;
            }
            double pointCalculate(Point p1) {
                //지역 내부 클래스에서 사용되는 지역 변수는 상수로 처리된다.
                //num=200; //지역변수는 상수로 바뀌므로 값을 변경할 수 없다.
                return Math.sqrt((this.x-p1.x)*(this.x-p1.x)+(this.y-p1.y)*(this.y-p1.y));
            }
        }
        Point c1 = new Point(100,200);
        Point c2 = new Point(50,70);
        return c1.pointCalculate(c2);


    }
    //==================지역 내부 클래스=====================


    public static void main(String[] args) {
        OutClass c1 = new OutClass(10,20);
        System.out.println("지역 내부 클래스 사용 : "+c1.localClassTest());

    }


}

 

지역 내부 클래스는 메서드나 블록 내부에서 선언된 클래스이며 해당 메서드나 블록 내부에서만 사용할 수 있다.

 

클래스의 외부 블록이나 메서드의 지역변수의 값은 상수로 인식된다. 따라서 내부 클래스 안에서 해당 지역변수를 접근은 가능하나 변경할 수 없다. 메서드 내부에 선언된 변수를 변경하려고 하면 다음과 같은 오류 메시지를 만날 수 있을 것이다.

Variable 'num' is accessed from within inner class, needs to be final or effectively final

 

 

 

 


익명 내부 클래스(Anonymous Inner Class)

 

익명 내부 클래스는 이름이 없는 내부 클래스로, 인터페이스나 추상 클래스의 구현을 간단하게 표현할 때 사용한다.

익명 내부 클래스는 변수에 직접 대입하는 경우도 있으며 메서드 내부에서 인터페이스나 추상 클래스를 직접 구현하는 경우도 있다.

 

interface InClass{
    int plusOperator(int num, int num2);
}


public class OutClass {
    private InClass innerClass = new InClass() {
        @Override
        public int plusOperator(int num, int num2) {
            return (num + num2);
        }
    };

    public OutClass(){};

    public static void main(String[] args) {
        OutClass c1 = new OutClass();
        c1.innerClass.plusOperator(100, 200); //변수에 직접 익명 내부 클래스 대입
    }


}

 

 

익명 내부 클래스는 보통 한 번만 사용되고, 해당 위치에서만 추상 클래스나 인터페이스의 간단한 구현이 필요할 때 사용된다. 위에서는 인터페이스를 구현하기 위해 클래스를 따로 정의할 필요 없이 익명 내부 클래스를 사용하여 필요한 동작을 구현하였다.

 

 

 

 

interface InClass{
    int plusOperator(int num, int num2);
}


public class OutClass {
    private InClass innerClass = (num, num2) -> (num + num2);

    public OutClass(){};

    public static void main(String[] args) {
        OutClass c1 = new OutClass();
        System.out.println(c1.innerClass.plusOperator(100, 200));
    }

}

 

인터페이스의 구현해야 할 메서드가 1개라면 다음과 같이 람다식을 통해서 코드를 더 간결하게 만들 수도 있다.

 

<같이 보기>

https://sjh9708.tistory.com/190

 

[Java] 람다식(Lambda Expression)과 함수형 프로그래밍

람다식(Lambda Expression) 람다식은 함수형 프로그래밍에서 사용되는 개념으로, 간결하고 명확한 방식으로 익명 함수를 표현하는 방법이다. 자바 8부터 도입되었으며, 함수형 인터페이스의 구현을

sjh9708.tistory.com

 

 

 


정리 : 내부 클래스들이 사용하기 유용한 경우

 

 

멤버 내부 클래스 : 외부 클래스의 인스턴스와 밀접한 관련이 있는 경우 -> 외부 클래스의 필드와 메서드에 쉽게 접근 가능

정적 내부 클래스 : 외부 클래스와 독립적으로 동작해야 하는 경우

지역 내부 클래스 :특정 메서드나 블록 내부에서만 사용되고, 해당 영역에서만 필요한 기능을 구현할 때 

익명 내부 클래스 :한 번만 사용되고, 해당 위치에서만 인터페이스나 추상 클래스의 필요한 간단한 구현이 필요할 때 유용

 

 

 

 

 

 

반응형

BELATED ARTICLES

more