- Spring Dto -- Nested Class?2021년 06월 04일 17시 16분 49초에 업로드 된 글입니다.작성자: jCurve728x90반응형
중첩 클래스 어떤 상황에서 써야 할까
스프링에서 컨트롤러에서 Dto 자주 사용하는데 이 Dto는 메서드 마다 새로 만드는 경우가 많은데, 재사용할 상황이 많이 안생겨서 이걸 굳이 Dto 패키지를 만들어서 거기에 넣어두거나 특정 도메인 패키지에 넣어둘 필요 없이 그냥 중첩 클래스로 쓰는게 좋지 않나? 라는 생각에서 시작했다.
일단 중첩 클래스 정리
중첩 클래스는
선언위치에 따른 분류 선언위치 설명 멤버 클래스 인스턴스 멤버 클래스 class A{
class B{ ...}
}A 클래스를 생성해야만 사용가능한 B 중첩 클래스 정적 멤버 클래스 class A{
static class B{...}
}A 클래스로 바로 접근 가능한 B 중첩 클래스 로컬 클래스 class A{
void method(){
class B{....}
}
}method()가 실행할 때만 사용할 수 있는 B 중첩 클래스 (중첩 클래스도 일단 클래스기 때문에 컴파일하면 바이트 코드 (.class) 파일이 별도로 생성된다.)
인스턴스 멤버 클래스는 인스턴스 필드와 메서드만 선언 가능한 중첩 클래스로 static은 사용이 불가능하다.
위 사진의Main 클래스 외부에서 InstanceInnerClass1의 객체를 생성하려면 Main클래스 객체를 생성하고 생성해야한다.
이런식으로
이런 방식 자체로 해당 내부 클래스의 접근을 한정적으로 제한할 수 있게 만드는 효과가 있다.
정적 멤버 클래스는 위와 다르게 바로 접근해서 생성 가능하고 모든 종류의 필드와 메서드 선언이 가능하다.
로컬 멤버 클래스는 메서드 내부에서만 사용되니까 접근 제한자나 static을 붙일 수 없다. 붙여도 그 의미가 필요 없기 때문이다.
로컬 클래스 내부는 인스턴스 필드와 메서드만 가능하다. 생각해보면 static은 왜 안되는지 알거다.
메서드 실행될 때만 로컬 클래스의 인스턴스를 생성해서 사용하는데 클래스 로딩 시점에 이미 그 값을 사용할 수 있어야 되는 건데 메서드 실행시에 인스턴스가 생성되는 로컬 클래스에서 static 필드라니 벌써 모순이다.
로컬 멤버 클래스는 사용해본 경험이 없어서 찾아보니 비동기 처리를 위해 스레드 객체를 만들 때 사용한다고 한다.
중첩 클래스의 접근 제한
바깥 필드와 메서드에서 사용 제한
인스턴스 멤버 클래스는 바깥 클래스의 인스턴스 필드의 초기값이나 인스턴스 메서드에서 객체 생성이 가능하지만 정적 필드의 초기값이나 정적 메서드에서는 객체를 생성할 수 없다.
정적 멤버 클래스는 모든 필드의 초기값이나 모든 메서드에서 객체 생성이 가능하다.
클래스 로딩 시점에 초기화가 완료된 static 멤버를 사용할 수 있어야하는데 인스턴스 클래스는 로딩 시점에 사용이 사용할 수 있는 상태가 아니기 때문에 위와 같은 에러가 나온다.
멤버 클래스에서 사용 제한
멤버 클래스 내부에서는 외부 클래스의 필드와 메서드에 접근 제한이 있는데
인스턴스 멤버 클래스는 외부 클래스의 모든 종류의 필드와 메서드에 접근이 가능한데
정적 멤버 클래스는 외부 클래스의 정적 필드, 정적 메서드만 접근할 수 있다.
정적 멤버 클래스는 static으로 선언되어 있기 때문에 외부 클래스에서도 클래스 로딩 시점에 사용할 수 있는 정적 필드와 정적 메서드만 접근 가능하다.
로컬 클래스에서 사용 제한
로컬 클래스 내부에서는 바깥 클래스의 필드나 메서드를 제한 없이 사용 가능한데,
메서드의 매개 변수나 로컬 변수를 로컬 클래스에서 사용할때 문제가 생긴다.
로컬 클래스는 메서드 실행이 끝나고 객체가 힙 메모리에 존재하는데 , 매개 변수나 로컬 변수는 스택 영영게 있다가 메서드 실행이 끝나면 사라지기 때문에 이 값을 로컬 클래스 객체에서 사용하면 문제가 생기는데,,
자바에서 이 문제 해결을 위해 컴파일 시점에 로커 클래스에서 사용하는 매개 변수나 로컬 변수의 값을 로컬 클래스 내부에 복사하고 사용한다.
그리고 혹시 매개변수나 로컬 변수가 수정되서 값이 변경되면 로컬 클래스에 복사해둔 값과 달라지니까 이 문제를 해결하기 위해 매개 변수나 로컬 변수를 final로 선언해서 막는다.
그래서 로컬 클래스에서 사용 가능한건 final로 선언한 매개변수와 로컬 변수 뿐이다.
자바 8부터는 final 선언을 하지 않아도 final 특성을 갖는다. 그래도 final을 선언하면 선언하지 않는 것과 차이가 있는데 복사 위치가 달라진다. 로컬 변수나 매개변수를 final로 선언하면 로컬 클래스의 메서드 내부 지역 변수로 값이 복사되는데 final 선언이 없으면 로컬 클래스의 필드로 복사된다.
중첩 클래스에서 바깥 클래스 참조 얻기
클래스 내부에서 this는 객체 자신의 참조이기 때문에 중첩 클래스에서 this 키워드를 사용하면 바깥 클래스 객체 참조가 아니라 중첩 클래스의 객체 참조가 되서 this.필드 , this.method()를 쓰면 중첩 클래스의 필드와 메서드가 사용된다.
바깥 클래스 참조를 얻으려면 this 앞에 클래스 이름을 붙여준다.
내생각은 그래
결과적으로 내부클래스는 내부 클래스를 포함하는 클래스 안에서 한정적으로 접근할때만 사용하고 여러 클래스에서 접근해야하면 외부 클래스로 사용하는 것이 맞는데,,,
미래에 지금 내가 만들고 있는 Dto를 접근할지 안할지 현재에 내가 알 수 없으니
일단 내부 클래스는 해당 클래스 안에서만 한정적으로 사용한다는 의미 부여가 될 때 사용해서 응집도 높게 쓰자.
코드 해석할 때 내부 클래스를 보고 이 Dto는 여기서만 쓰이는 구나! 라고 생각이 되게
끝
반응형'Spring' 카테고리의 다른 글
JWT Spring-Security-Test로 테스트시 인증정보 주입 (4) 2021.07.22 Jpa Entity 연관관계가 참조되어있는 객체 삭제 (0) 2021.06.15 Jpa Named Query 에러와 @Modifying , @Transactional (0) 2021.06.15 FormData 파일과 객체 한번에 보내기 (0) 2021.05.26 MultiPartFile 저장시 LocalDateTime 과 for문 (0) 2021.04.07 댓글