순간을 성실히, 화려함보단 꾸준함을

[static inner class]non-static inner classes like this can only by instantiated using default 본문

나의 개발 메모장

[static inner class]non-static inner classes like this can only by instantiated using default

폭발토끼 2022. 1. 4. 23:02

김영한님 강의를 듣고 난 후 코드를 작성하고 실행시켰더니 이런 에러메세지가 출력이 되었다.

재미난 부분인데 왜 이런 메세지가 출력이 되는 것 일까?

먼저 코드부터 살펴보자

package jpabook1.jpashop.api;

import jpabook1.jpashop.domain.Member;
import jpabook1.jpashop.service.MemberService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequiredArgsConstructor
public class MemberApiController {

    private final MemberService memberService;

    @PostMapping("/api/v1/members")
    public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member){
        Long id = memberService.join(member);
        return new CreateMemberResponse(id);
    }
    @PostMapping("api/v2/members")
    public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest request){
        Member member = new Member();
        member.setName(request.getName());

        Long id = memberService.join(member);
        return new CreateMemberResponse(id);
    }
    @Data
    class CreateMemberRequest{
        private String name;
    }
    @Data
    class CreateMemberResponse{
        private Long id;

        public CreateMemberResponse(Long id) {
            this.id = id;
        }
    }
}

처음 작성한 코드이고, postman을 통해 json 형식으로 "name" : "kim" 이라는 데이터를 넘겨주었다. 그러나 제목과 같은 에러가 발생한 것을 확인할 수 있었는데

원인은 바로 static 키워드를 CreateMemberRequest class 에 붙여주질 않았기 때문이다.

그럼 대체 왜????? static 키워드를 붙여줘야 하는 것 일까?

백기선님과 같이 진행한 자바스터디에서 중접클래스와 내부클래스에 관해서 공부를 했었다.
이때 클래스 내부에 클래스가 선언될 수가 있고, static 키워드가 붙은 클래스와 아닌 클래스로 나눌 수 있었다.

static키워드를 붙이지 않은 클래스는 반드시 반드시 외부 클래스(Outer class)를 먼저 인스턴스화 시키고 난 후 (new 연산자로 메모리 할당) 그 다음 inner class에 접근이 가능했었다.

public class ClassA{
    class InnerClass{
    }
}
public class ClassB{
    public static void main(String[] args) {
        ClassA classA = new ClassA();
        ClassA.ClassAInner classAInner = new ClassA.ClassAInner();  //컴파일 오류
    }
}

반면에 static 키워드가 붙은 내부클래스는 별도로 외부 클래스(Outer class)를 인스턴스화 시킬 필요도 없이 직접적으로 접근이 가능했었다.

public class ClassA{
    static class InnerClass{
    }
}
public class ClassB{
    public static void main(String[] args) {
        ClassA classA = new ClassA();
        ClassA.ClassAInner classAInner = new ClassA.ClassAInner();  //정상
    }
}

그럼 다시 처음코드로 돌아가서 어디서 문제가 발생한 것일까?

@PostMapping("api/v2/members")
    public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest request){
        Member member = new Member();
        member.setName(request.getName());

        Long id = memberService.join(member);
        return new CreateMemberResponse(id);
    }

바로 이부분이다. CreateMemberRequest request 라는 파라미터는 외부에서 이 객체를 직접 생성하고 들어오는데 정작 CreateMemberRequest 라는 내부 클래스(Inner class)는 static으로 선언되어 있지 않아 생성자체가 불가능 한 것이다.

따라서, static 키워드를 붙여줘야 하는 것이다.

오늘 일지 끝~