Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Archives
Today
Total
관리 메뉴

개발자

[class] 내부 클래스, 내부 static 클래스 본문

개발자/workflow 리팩토링 프로젝트(SpringBoot,JPA,MySQL)

[class] 내부 클래스, 내부 static 클래스

GoGo개발 2023. 5. 2. 16:39
내부 클래스

 

내부 클래스는 클래스 내에 선언되는 클래스이다. 내부의 클래스가 외부 클래스와 연관관계가 깊으며, 다른 클래스에서 사용되지 않을 때 내부클래스를 사용하게된다. 이러한 특징 때문에 내부 클래스는 외부 클래스와 강하게 결합된 클래스를 만들 수 있다.

클래스가 여러 클래스와 관계를 맺지 않고 하나의 특정 클래스와만 관계를 맺는다면, 외부에 클래스를 새로 작성하는 것이 아닌 내부 클래스로 작성할 수 있다.

 

그렇다면 내부 클래스는 왜 사용하지?

 

내부 클래스의 특징

 

1. 클래스를 논리적으로 그룹화

클래스가 여러 클래스와 관계를 맺지 않고 하나의 특정 클래스와만 관계를 맺는다면, 외부에 클래스를 새로 작성하는 것이 아닌 내부 클래스로 작성할 수 있다.

이런 경우 내부 클래스와 외부 클래스를 함께 관리하는 것이 가능해 유지보수 면에서나 코드 이해성 면에서 편리해진다.

또한 내부 클래스로 인해 새로운 클래스를 생성하지 않아도 되므로 패키지를 간소화할 수 있다.

 

2. 더욱 타이트한 캡슐화의 적용

내부 클래스에 private 제어자를 적용해줌으로써, 캡슐화를 통해 클래스를 내부로 숨길 수 있다.

즉, 캡슐화를 통해 외부에서의 접근을 차단하면서도, 내부 클래스에서 외부 클래스의 멤버들을 제약 없이 쉽게 접근할 수 있어 구조적인 프로그래밍이 가능해 진다. 그리고 클래스 구조를 숨김으로써 코드의 복잡성도 줄일 수 있다.

 

class Creature {
    private int life = 50;
	
    // private class 로, 오로지 Creature 외부 클래스에서만 접근 가능한 내부 클래스로 설정
    private class Animal {
        private String name = "호랑이";

        int getOuter() {
            return life; // 외부 클래스의 private 멤버를 제약 없이 접근 가능
        }
    }

    public void method() {
        Animal animal = new Animal(); 

        // Getter 없이 내부 클래스의 private 멤버에 접근이 가능
        System.out.println(animal.name); // 호랑이

        // 내부 클래스에서 외부 클래스이 private 멤버를 출력
        System.out.println(animal.getOuter()); // 50
    }
}

 

3. 가독성이 좋고 유지 관리가 쉬운 코드

결국은 내부 클래스를 작성하는 경우 클래스를 따로 외부에 작성하는 경우보다, 물리적으로 논리적으로 외부 클래스에 더 가깝게 위치하게 된다. 따라서 시각적으로 읽기가 편해질 뿐 아니라 유지보수에 있어 이점을 가지게 된다.

한 클래스를 다른 클래스의 내부 클래스로 선언하면 두 클래스 멤버들 간에 서로 자유로이 접근할 수 있고, 그리고 외부에는 불필요한 클래스를 감춰서 클래스간의 연관 관계 따지는 것과 같은 코드의 복잡성을 줄일 수 있다는 장점이 있기 때문이다.

간단하게 말하자면 어차피 A 클래스안에서만 사용하기 위한 클래스이니 괜히 연관관계 생각없이 내부에 선언해 직관적으로 사용하자는 취지인 것이다.

 

<내 프로젝트에 적용하면>

나는 command 클래스에 내부클래스를 사용할 것이다. 요청할때 받을수있는 데이터랑 응답으로 줄수있는데이터가다르기 때문에 command와 vo를 분리하였는데 예를들면 회원가입할때 id는 요청으로 받을 수 있지만 나중에 id를 바꿀수없기때문에 수정에서는 id를 파라미터을 정의자체 하지 않는다. 

 

  1. 코드 구조화: 내부 클래스는 클래스의 구조를 분리하여 코드를 구조화할 수 있습니다. 위 코드에서는 CreateUser와 UpdateUser 클래스가 UserCommand 클래스의 일부분으로 구현되어 있습니다. 이를 통해 UserCommand 클래스가 CreateUser와 UpdateUser 클래스의 목적에 맞게 더욱 명확하고 구체적인 역할을 수행하게 됩니다.
  2. 정보 은닉: 내부 클래스를 사용하여 필요한 기능을 구현함으로써, 외부 클래스의 구현 세부 정보를 숨길 수 있습니다. 위 코드에서 CreateUser와 UpdateUser 클래스는 UserCommand 클래스의 일부분으로 구현되어 있으므로, UserCommand 클래스의 구현 세부 정보를 숨길 수 있습니다.
  3. 코드 재사용: 내부 클래스를 사용하여 코드를 재사용할 수 있습니다. 위 코드에서는 CreateUser와 UpdateUser 클래스가 UserCommand 클래스에서 각각 User 객체를 생성하고 업데이트하는 목적으로 사용되고 있습니다. 이러한 목적에 따라 CreateUser와 UpdateUser 클래스는 UserCommand 클래스를 위한 특별한 도우미 클래스로서 역할을 하며, 다른 클래스에서도 활용이 가능합니다.
  4. 가독성: 내부 클래스를 사용하여 코드의 가독성을 높일 수 있습니다. 위 코드에서는 CreateUser와 UpdateUser 클래스가 UserCommand 클래스 내부에 정의되어 있으므로, 코드를 읽을 때 UserCommand 클래스의 구성 요소들을 빠르게 파악할 수 있습니다. 이를 통해 코드의 가독성을 높일 수 있습니다.

-> 추후 request로 변경했다

 

내부클래스에서 static 클래스를 사용하는 이유
일반적으로 내부 인스턴스 클래스를 만들기 위해서는 먼저 외부 클래스를 초기화한뒤 내부 클래스를 초기화해야 한다. 이러한 단계 과정 때문에 inner 클래스는 자신을 만들어준 인스턴스에 대한 '외부 참조'를 갖게 된다.
심지어 내부 클래스가 외부의 멤버를 사용하지 않아도, 숨겨진 외부 참조가 생성되게 된다.
즉, 비정적(non-static) 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결된다.

그래서 결론부터 말하자면 
static이 아닌 내부 인스턴스 클래스는 외부와 연결이 되어 있어 '외부 참조'를 갖게되어 메모리를 더 먹고, 느리며, 또한 GC 대상에서 제외되는 여러 문제점을 일으키기 때문이다. 그래서 내부 클래스가 외부 클래스의 멤버를 가져와 사용하는 경우가 아닌 경우반드시 내부 클래스를 선언 할 때는 static 키워드를 붙여주어야 한다

중요한건 내부 static클래스는 우리가 아는 static의 개념과 조금 다른데 알아보자

 

가장 많은 사람들이 실수하는 오해가 static 클래스가 그 외의 static 필드 변수나 static 메소드와 같이, 'static 이니까 메모리에 하나만 올라가는 인스턴스'로 착각 한다는 점이다.

우선 결론부터 말하면 static 클래스는, 키워드가 static이 들어갔을 뿐이지, 우리가 알던 static 멤버와는 전혀 다른 녀석이다.

다음 코드를 보면 static 변수와 내부 인스턴스 클래스 그리고 내부 static 클래스가 있다.

이들을 각각 메인 메소드에서 변수로 받아 같은지 다른지 비교해보면, static 변수는 우리의 예상대로 메모리에서 한번만 생성 되니까 반환 되는 데이터는 같다.

하지만 내부 static 클래스는 일반 클래스처럼 초기화를 할때마다 다른 객체가 만들어짐을 볼 수 있다. (static 인데 말이다)

 
 static Integer num = new Integer(0);

    // 내부 인스턴스 클래스
    class InnerClass{
    }

    // 내부 스태틱 클래스
    static class InnerStaticClass{
    }
    
    public static void main(String[] args) {

        // 스태틱 필드 변수는 유일해서 서로 같다
        Integer num1 = Main.num;
        Integer num2 = Main.num;
        System.out.println(num1 == num2); // true


        // 생성된 내부 클래스 인스턴스는 서로 다르다
        Main.InnerClass inner1 = new Main().new InnerClass();
        Main.InnerClass inner2 = new Main().new InnerClass();
        System.out.println(inner1 == inner2); // false


        // 생성된 내부 스태틱 클래스 인스턴스는 서로 다르다
        Main.InnerStaticClass static1 = new InnerStaticClass();
        Main.InnerStaticClass static2 = new InnerStaticClass();
        System.out.println(static1 == static2); // false
    }
}

 

복잡하게 생각할 필요없이 static 클래스는 static 이라고 해서 메모리에 한번만 로드되는 객체 개념이 아닌 것이다.

즉, 내부 인스턴스 클래스 처럼 외부 인스턴스를 먼저 선언하고 초기화해야 하는 선수 작업 필요 없이, 내부 클래스의 인스턴스를 바로 생성할 수 있다는 차이점이 존재 할 뿐이다.

 

내부 클래스는 static 영역에 할당, 내부클래스 필드는 heap영역에 들어가서 GC관리는 받는것 같다
더 공부하다가 느낀건데... 중요한건 내부클래스를 잘 이해하려면 메모리영역에 대한 지식이필요하고 메모리영역을 이해하려면 GC에 대해서도 알아야한다.... static/stack/heap 메모리영역과 CG에 관한 포스팅을 이어서 쓰고 링크하겠다 같이공부해야 좋을것 같다!

 

 

출처

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4Inner-Class-%EC%9E%A5%EC%A0%90-%EC%A2%85%EB%A5%98

 

☕ 내부 클래스(Inner Class) 장점 & 종류 총정리

내부 클래스 (Inner Class) 내부 클래스(inner class)란 하나의 클래스 내부에 선언된 또 다른 클래스를 의미한다. 보통 사용자 클래스 자료형이 필요하면, 메인 클래스 외부에 선언하거나, 따로 독립적

inpa.tistory.com

 

static에 대해서 참고 블로그

https://vaert.tistory.com/101

 

[Java] Static 키워드 바로 알고 사용하자

자바를 한번쯤 공부해본사람이라면 static키워드를 모르지는 않을 것입니다. 하지만, 바르게 알고 있는 사람들은 그리 많지 않습니다. 자바경력자를 면접볼 때 static키워드에 대해서 질문하곤 합

vaert.tistory.com

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9E%90%EB%B0%94%EC%9D%98-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%8A%94-static-%EC%9C%BC%EB%A1%9C-%EC%84%A0%EC%96%B8%ED%95%98%EC%9E%90

 

☕ 내부 클래스는 static 으로 선언 안하면 큰일 난다

Inner 클래스의 문제점 인텔리제이와 같은 IDE에서 내부 클래스를 선언하여 사용하면 다음과 같이 경고 메세지가 뜰 것이다. (내부 클래스가 외부의 멤버를 참조하여 사용하지 않을 경우) 메세지

inpa.tistory.com

 

정적 메소드는 유틸리티 함수를 만드는데 유용하게 사용됩니다.

https://kingofbackend.tistory.com/131

 

[Java] 자바 static의 의미와 사용법

정적(Static)이란? 정적(static)은 고정된이란 의미를 가지고 있습니다. Static이라는 키워드를 사용하여 Static변수와 Static메소드를 만들 수 있는데 다른말로 정적필드와 정적 메소드라고도 하며 이

kingofbackend.tistory.com

 

더공부할 블로그

https://velog.io/@mooh2jj/Java-static-%EB%B3%80%EC%88%98-static-%EB%A9%94%EC%84%9C%EB%93%9C-%EA%B7%B8%EB%A6%AC%EA%B3%A0-static-%ED%81%B4%EB%9E%98%EC%8A%A4

 

[Java] static 변수, static 메서드 그리고 static 클래스

satic 클래스는 중첩 클래스(nested class)를 사용할 때 사용한다. 다음 코드를 보자.이런식으로 쓰면 다음 경로가 날아온다.경고: Inner class may be 'static'Reports any inner classes which may safely

velog.io

https://johngrib.github.io/wiki/java/inner-class-may-be-static/

 

Java의 내부 클래스는 static으로 선언하자

메모리를 더 먹고, 느리고, 바깥 클래스가 GC 대상에서 빠질 수 있다

johngrib.github.io

static 관련

https://dejavuhyo.github.io/posts/java-static/

 

Java Static 키워드

1. static 키워드 구조 Java 프로그래밍 언어에서 키워드 static은 특정 멤버가 해당 유형의 인스턴스가 아니라 유형 자체에 속한다는 것을 의미한다.

dejavuhyo.github.io