개요
java@RestController @RequiredArgsConstructor @RequestMapping("/api/users") public class UserController { private final UserService userService; @GetMapping("/{userId}") public UserInfoResponse getUserById(@PathVariable String userId) { return userService.getUserById(userId) } ... }
문득 개발을 하다가 @~ArgsConstructor에 대해 궁금증이 생겼다.
자연스럽게 필요한 코드에 해당 어노테이션들을 달지만 왜 달아야하는지 다시 공부한다.
간단하게 말하면 해당 어노테이션들은 다음과 같다.
-
@NoArgsConstructor: parameter가 없는 default 생성자를 생성
-
@AllArgsConstructor: 모든 field 값을 paramter로 받는 생성자를 생성
-
@RequiredArgsConstructor: final이나 @NonNull로 선언된 field만을 paramter로 받는 생성자를 생성
이 어노테이션들은 객체 내부에 선언되어있는 특정 field마다 딱 1개의 값을 생성자 parameter로 받고, 이 값을 단순히 field에 assign 해주는 생성자를 생성한다.
각 생성자들의 특징
@NoArgsConstructor
@NoArgsConstructor을 사용하면, class에 명시적으로 선언된 생성자가 없더라도 instance를 생성할 수 있다.
java@NoArgsConstructor public class User { private String userName; private String userEmail; }
위의 코드를 빌드하면 다음과 같아진다.
javapublic class User { private String userName; private String userEmail; public User(){} }
@AllArgsConstructor
@AllArgsConstructor을 사용하면, class의 모든 field를 한 번에 초기화할 수 있다.
java@AllArgsConstructor public class User { private String userName; private String userEmail; }
위의 코드를 빌드하면 다음과 같아진다.
javapublic class User { private String userName; private String userEmail; public User(String userName, String userEmail) { this.userName = userName; this.userEmail = userEmail; } }
@RequiredArgsConstructor
@RequiredArgsConstructor을 사용하면, class가 의존하는 field를 간단하게 초기화할 수 있다.
※ final로 선언하면 한 번 초기화된 변수는 변경할 수 없는 상수값이 된다. → 불변성 유지
(단, 객체를 final로 선언하면 다른 객체로 변경할 수는 없지만 객체의 속성은 변경 가능하다.)
java@RequiredArgsConstructor public class User { private final String userName; private final String userEmail; }
위의 코드를 빌드하면 다음과 같아진다.
javapublic class User { private String userName; private String userEmail; public User(final String userName, final String userEmail) { this.userName = userName; this.userEmail = userEmail; } }
생성자 어노테이션의 옵션
또한 생성자 어노테이션에는 다음과 같은 옵션들이 있다.
-
staticName: 정적 팩토리 메서드를 생성
-
access: 접근제어자를 지정 (default: public)
-
onConstructor: 생성자의 접근제어자를 설정 (default: public)
-
force: final field가 선언된 경우 compile 타임에 기본값을 0 / null / false로 설정
staticName
모든 생성자 어노테이션에 사용될 수 있다.
java@AllArgsConstructor(staticName = "of") public class User { private String userName; private String userEmail; }
위의 코드를 빌드하면 다음과 같아진다.
java@AllArgsConstructor(staticName = "of") public class User { private String userName; private String userEmail; public static User of(String userName, String userEmail) { new User(userName, userEmail); } }
access
access 옵션엔 다음과 같은 접근제어자가 있다.
-
PUBLIC: 모든 클래스에서 생성자에 접근 가능
-
PROTECTED: 같은 패키지의 클래스와 상속받은 클래스에서 생성자에 접근 가능
-
PACKAGE: 같은 패키지의 클래스에서 생성자에 접근 가능
-
PRIVATE: 해당 클래스 내부에서만 생성자에 접근 가능 ※ NONE과 MODULE도 있지만, 일반적으로 사용하지 않는다.
force
@NoArgsConstructor 어노테이션에만 사용이 가능하다. force 옵션을 지정할 경우 primitive type에 맞는 기본값이 설정된다.
java@NoArgsConstructor(force = true) public class User { private final String userName; private final int userAge; private String userEmail; }
위의 코드는 compile 시점에 다음과 같아진다.
javapublic class User { private final String userName = null; private final int userAge = 0; private String userEmail; }