프로그래밍 언어/JAVA

JAVA: 중첩 클래스(Nested class)와 내부 클래스(Inner Classes)

구루다 2023. 3. 3. 10:03
반응형

JAVA: 중첩 클래스(Nested class)와 내부 클래스(Inner Classes)

자바(Java)는 객체 지향 프로그래밍 언어로써 클래스(class)를 중심으로 구성되어 있다. 클래스는 프로그램을 구성하는 요소 중 하나로, 데이터와 메서드(method)로 이루어져 있다. 중첩 클래스(nested class)는 자바에서 클래스 안에 또 다른 클래스를 정의하는 방법 중 하나로, 내부 클래스(inner class)는 중첩 클래스 중에서 클래스 안에서만 사용하는 클래스를 말한다. 이번 글에서는 중첩 클래스와 내부 클래스에 대해 자세히 알아보도록 하자.

 

JAVA 8-3
JAVA 8-3

 

중첩 클래스

자바에서는 클래스 내부에 또 다른 클래스를 선언할 수 있다. 이렇게 선언된 클래스를 중첩 클래스라고 한다. 중첩 클래스는 다른 클래스 내부에 선언되기 때문에, 외부 클래스의 멤버에 쉽게 접근할 수 있다는 장점이 있다. 중첩 클래스는 선언 위치와 선언 방법에 따라 다음과 같이 4가지 종류로 나눌 수 있다.

 

반응형

 

정적 중첩 클래스

정적 중첩 클래스(static nested class)는 다른 클래스의 멤버와 같은 위치에 선언되지만, 정적 멤버와 같은 성격을 가진다. 따라서 정적 중첩 클래스는 외부 클래스의 인스턴스와는 상관없이 사용할 수 있다. 정적 중첩 클래스를 사용하면, 클래스 간의 응집도(cohesion)를 높일 수 있고, 코드의 가독성을 높일 수 있다는 장점이 있다.

public class Outer {
    private static int num;
    
    public static class StaticNested {
        public void printNum() {
            System.out.println(num);
        }
    }
}

위의 코드는 정적 중첩 클래스를 사용한 예시이다. Outer 클래스 안에 StaticNested 클래스를 선언하였고, 이 클래스는 num이라는 정적 멤버에 접근하여 출력하는 printNum() 메서드를 가지고 있다. StaticNested 클래스를 사용하려면 다음과 같이 코드를 작성하면 된다.

Outer.StaticNested nested = new Outer.StaticNested();
nested.printNum();  // 0

 

300x250

 

비정적 중첩 클래스

비정적 중첩 클래스(non-static nested class), 또는 내부 클래스(inner class)는 다른 클래스의 멤버와 같은 위치에 선언되지만, 정적 멤버와 다르게 외부 클래스의 인스턴스와 관련이 있다. 따라서 비정적 중첩 클래스는 외부 클래스의 인스턴스에만 접근할 수 있고, 이를 통해 외부 클래스의 멤버에 쉽게 접근할 수 있다.

public class Outer {
    private int num;

    public class Inner {
    public void printNum()
        System.out.println(num);
        }
    }
}

sql Copy code 위의 코드는 비정적 중첩 클래스를 사용한 예시이다. Outer 클래스 안에 Inner 클래스를 선언하였고, 이 클래스는 num이라는 멤버에 접근하여 출력하는 printNum() 메서드를 가지고 있다. Inner 클래스를 사용하려면 다음과 같이 코드를 작성하면 된다.

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.printNum();  // 0

 

지역 클래스

지역 클래스(local class)는 메서드 내부에서 선언되는 클래스이다. 지역 클래스는 외부 클래스와 같은 방법으로 선언될 수 있지만, 지역 변수와 같이 메서드 내부에서만 사용할 수 있다.

public class Outer {
    public void print() {
        int num = 10;

        class Local {
            public void printNum() {
                System.out.println(num);
            }
        }

        Local local = new Local();
        local.printNum();  // 10
    }
}

위의 코드는 지역 클래스를 사용한 예시이다. Outer 클래스의 print() 메서드 내부에서 Local 클래스를 선언하였고, 이 클래스는 num이라는 지역 변수에 접근하여 출력하는 printNum() 메서드를 가지고 있다. Local 클래스를 사용하려면 다음과 같이 코드를 작성하면 된다.

Outer outer = new Outer();
outer.print();

 

익명 클래스

익명 클래스(anonymous class)는 클래스의 이름이 없는 클래스이다. 익명 클래스는 선언과 동시에 객체를 생성할 때 사용한다. 익명 클래스는 보통 인터페이스나 추상 클래스를 구현하거나 상속받을 때 사용한다.

public class Outer {
    public void print() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread is running...");
            }
        });

        thread.start(); 
    }
}

위의 코드는 익명 클래스를 사용한 예시이다. Runnable 인터페이스를 구현하여 Thread 객체를 생성하였고, 이 객체를 실행시키면 "Thread is running..."이라는 메시지가 출력된다.

 

 

내부 클래스

내부 클래스는 중첩 클래스 중에서 클래스 안에서만 사용하는 클래스를 말한다. 내부 클래스는 외부 클래스의 멤버에 쉽게 접근할 수 있기 때문에, 코드의 가독성과 유지 보수성을 높일 수 있다는 장점이 있다. 내부 클래스는 다음과 같이 4가지 종류로 나눌 수 있다.

 

인스턴스 내부 클래스

인스턴스 내부 클래스(instance inner class)는 비정적 중첩 클래스와 같은 성격을 가진다. 인스턴스 내부 클래스는 외부 클래스의 인스턴스와 관련이 있기 때문에, 외부 클래스의 멤버에 쉽게 접근할 수 있다.

public class Outer {
    private int num;

    public class Inner {
        public void printNum() {
            System.out.println(num);
        }
    }

    public void print() {
        Inner inner = new Inner();
        inner.printNum();  // 0
    }
}

위의 코드는 인스턴스 내부 클래스를 사용한 예시이다. Outer 클래스 안에 Inner 클래스를 선언하였고, Inner 클래스는 num이라는 멤버에 접근하여 출력하는 printNum() 메서드를 가지고 있다. Inner 클래스를 사용하려면 Outer 클래스의 객체를 생성한 후, Inner 클래스의 객체를 생성하면 된다.

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.printNum();  // 0

 

정적 내부 클래스

정적 내부 클래스(static inner class)는 인스턴스 내부 클래스와 달리, 외부 클래스의 인스턴스와 관련이 없다. 정적 내부 클래스는 외부 클래스의 정적 멤버에만 접근할 수 있기 때문에, 외부 클래스의 인스턴스 생성과 무관하게 사용할 수 있다.

public class Outer {
    private static int num;

    public static class Inner {
        public void printNum() {
            System.out.println(num);
        }
    }

    public void print() {
        Inner inner = new Inner();
        inner.printNum();  // 0
    }
}

위의 코드는 정적 내부 클래스를 사용한 예시이다. Outer 클래스 안에 Inner 클래스를 선언하였고, Inner 클래스는 num이라는 정적 멤버에 접근하여 출력하는 printNum() 메서드를 가지고 있다. Inner 클래스를 사용하려면 다음과 같이 코드를 작성하면 된다.

Outer.Inner inner = new Outer.Inner();
inner.printNum();  // 0

 

지역 내부 클래스

지역 내부 클래스(local inner class)는 지역 클래스와 같은 성격을 가지지만, 클래스가 메서드 내부가 아닌 블록 내부에 선언된다는 점에서 차이가 있다.

public class Outer {
    public void print() {
        int num = 10;

        class Local {
            public void printNum() {
                System.out.println(num);
            }
        }

        Local local = new Local();
        local.printNum();  // 10
    }
}

위의 코드는 지역 내부 클래스를 사용한 예시이다. Outer 클래스의 print() 메서드 내부에서 Local 클래스를 선언하였고, 이 클래스는 num이라는 지역 변수에 접근하여 출력하는 printNum() 메서드를 가지고 있다. Local 클래스를 사용하려면 다음과 같이 코드를 작성하면 된다.

Outer outer = new Outer();
outer.print();

 

익명 내부 클래스

익명 내부 클래스(anonymous inner class)는 익명 클래스와 같은 성격을 가지지만, 클래스가 외부 클래스의 멤버에 접근할 수 있기 때문에, 인스턴스 내부 클래스와 비슷한 용도로 사용된다. 익명 내부 클래스는 인터페이스나 추상 클래스의 구현체를 만들 때 주로 사용된다.

public class Outer {
    public void print() {
        Runnable r = new Runnable() {
            public void run() {
                System.out.println("Hello, world!");
            }
        };

        Thread t = new Thread(r);
        t.start();
    }
}

위의 코드는 익명 내부 클래스를 사용한 예시이다. Outer 클래스의 print() 메서드 내부에서 Runnable 인터페이스의 구현체를 익명 내부 클래스로 생성하였고, 이 구현체는 run() 메서드를 오버라이드하여 "Hello, world!"를 출력한다. 이 구현체를 사용하여 Thread 객체를 생성하고 실행하면, "Hello, world!"가 출력된다.

Outer outer = new Outer();
outer.print();  // "Hello, world!"

 

 

결론

Nested와 Inner 클래스는 Java에서 클래스를 더욱 유연하게 사용할 수 있도록 해주는 기능이다. 이를 통해 클래스를 더욱 모듈화하고 캡슐화할 수 있으며, 코드의 가독성과 유지보수성을 높일 수 있다. 인스턴스 내부 클래스, 정적 내부 클래스, 지역 내부 클래스, 익명 내부 클래스 등 다양한 종류의 Nested와 Inner 클래스가 제공되기 때문에, 상황에 맞게 적절한 클래스를 사용하여 코드를 작성해야 한다.

 

 

 

JAVA에서 추상 클래스 (Abstract Classes)

JAVA에서 추상 클래스 (Abstract Classes) Java는 객체 지향 프로그래밍 언어로서 다양한 기능과 특징을 갖추고 있습니다. 그 중에서도 추상 클래스는 Java에서 매우 중요한 개념 중 하나입니다. 이번 글

gruda.tistory.com

 

JAVA 인터페이스 개념과 활용

JAVA 인터페이스 개념과 활용 JAVA에서 인터페이스(Interface)는 클래스와 비슷한 개념으로, 추상 메소드와 상수(constant)만을 포함할 수 있습니다. 인터페이스는 클래스와 달리 인스턴스를 생성할 수

gruda.tistory.com

 

JAVA에서의 생성자와 소멸자

JAVA에서의 생성자와 소멸자 객체 지향 프로그래밍에서 클래스는 객체를 생성하기 위한 청사진(blueprint)이며, 객체는 클래스를 기반으로 생성된 인스턴스입니다. JAVA에서는 클래스를 정의할 때

gruda.tistory.com

 

Java에서 상속과 다형성의 이해

Java에서 상속과 다형성의 이해 Java는 객체 지향 프로그래밍 언어 중 하나로, 객체 지향 프로그래밍의 핵심 개념인 상속과 다형성을 지원합니다. 상속은 객체 지향 프로그래밍에서 객체들 간의

gruda.tistory.com

 

320x100
728x90