220831 첫글자만 소문자일 때 값이 null

Jongleee·2022년 8월 31일
2

TIL

목록 보기
41/737

상황

dto를 쓰는 경우에 dDay와 같이 첫글자만 소문자일 때 값이 null로 들어가는 문제가 발생함.

시도한 방법

  1. dto를 수정함
  2. 빌더패턴 사용
    ->두 방법 다 계속 dDay에 null값이 들어감

원인

1. JavaBeans 규약

JavaBeans 는 메서드 이름에서 필드명을 추출할 때 일정한 규칙이 존재.

Java Bean 규약의 8.8 Capitalization of inferred names 챕터

When we use design patterns to infer a property or event name, we need to decide what rules to follow for capitalizing the inferred name.
If we extract the name from the middle of a normal mixedCase style Java name then the name will, by default, begin with a capital letter.
Java programmers are accustomed to having normal identifiers start with lower case letters.
Vigorous reviewer input has convinced us that we should follow this same conventional rule for property and event names.

Thus when we extract a property or event name from the middle of an existing Java name, we normally convert the first character to lower case.
However to support the occasional use of all upper-case names, we check if the first two characters of the name are both upper case and if
so leave it alone. So for example,

“FooBah” becomes “fooBah”
“Z” becomes “z”
“URL” becomes “URL”

We provide a method Introspector.decapitalize which implements this conversion rule.

즉, 클래스의 이름은 일반적으로 대문자로 시작하지만, 개발자들은 식별자가 소문자로 시작하는 것에 익숙하기 때문에 첫 번째 글자를 소문자로 변환해줌

다만, 모든 문자를 대문자로 사용하는 경우를 판별하기 위해 첫 두 문자가 모두 대문자인지를 확인하고 두 글자가 대문자일때는 변환하지 않음

이를 java.beans 패키지에 있는 Introspector 클래스를 통해 확인해보면

public class Introspector {
    // ...

    public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                        Character.isUpperCase(name.charAt(0))){
            return name;
        }
        char chars[] = name.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }

    // ...
}

결국 맨 앞 두개가 전부 대문자라면 그대로 리턴하고 아니라면 맨 앞 문자 하나만 소문자로 바꿔서 리턴.

2. Lombok의 Getter 생성 규칙

get 다음에 필드명의 맨 앞 글자를 대문자로 바꿔서 getName() 의 형태를 만들어 줌.

3. 결론

Lombok 이 getDDay 로 생성해주고 java beans 을 거치면 DDay가 되어서 필드명인 dDay와 일치하지 않아 null값이 들어오게 됨.

해결 방법

  1. dueDate와 같이 변수명을 수정함
  2. 인텔리제이 Generator 의 Getter 생성 규칙을 이용
public class RequestDto {
    private String dDay;

    public String getdDay() {
        return dDay;
    }
}

Lombok 대신 인텔리제이에서 제공하는 제네레이터로 Getter 를 만들어 getDDay 대신에 getdDay 로 만들어 필드명 변경으로 인한 null값 이슈를 피할 수 있음

1개의 댓글

comment-user-thumbnail
2022년 9월 1일

트러블슈팅 잘봤습니다.

답글 달기