@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을 사용하면, class에 명시적으로 선언된 생성자가 없더라도 instance를 생성할 수 있다.
@NoArgsConstructor
public class User {
private String userName;
private String userEmail;
}
위의 코드를 빌드하면 다음과 같아진다.
public class User {
private String userName;
private String userEmail;
public User(){}
}
@AllArgsConstructor을 사용하면, class의 모든 field를 한 번에 초기화할 수 있다.
@AllArgsConstructor
public class User {
private String userName;
private String userEmail;
}
위의 코드를 빌드하면 다음과 같아진다.
public class User {
private String userName;
private String userEmail;
public User(String userName, String userEmail) {
this.userName = userName;
this.userEmail = userEmail;
}
}
@RequiredArgsConstructor을 사용하면, class가 의존하는 field를 간단하게 초기화할 수 있다.
※ final로 선언하면 한 번 초기화된 변수는 변경할 수 없는 상수값이 된다. → 불변성 유지
(단, 객체를 final로 선언하면 다른 객체로 변경할 수는 없지만 객체의 속성은 변경 가능하다.)
@RequiredArgsConstructor
public class User {
private final String userName;
private final String userEmail;
}
위의 코드를 빌드하면 다음과 같아진다.
public 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로 설정
모든 생성자 어노테이션에 사용될 수 있다.
@AllArgsConstructor(staticName = "of")
public class User {
private String userName;
private String userEmail;
}
위의 코드를 빌드하면 다음과 같아진다.
@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 옵션엔 다음과 같은 접근제어자가 있다.
PUBLIC: 모든 클래스에서 생성자에 접근 가능
PROTECTED: 같은 패키지의 클래스와 상속받은 클래스에서 생성자에 접근 가능
PACKAGE: 같은 패키지의 클래스에서 생성자에 접근 가능
PRIVATE: 해당 클래스 내부에서만 생성자에 접근 가능
※ NONE과 MODULE도 있지만, 일반적으로 사용하지 않는다.
@NoArgsConstructor 어노테이션에만 사용이 가능하다. force 옵션을 지정할 경우 primitive type에 맞는 기본값이 설정된다.
@NoArgsConstructor(force = true)
public class User {
private final String userName;
private final int userAge;
private String userEmail;
}
위의 코드는 compile 시점에 다음과 같아진다.
public class User {
private final String userName = null;
private final int userAge = 0;
private String userEmail;
}