printf-style
포맷 문자열은 컴파일러를 통해 검증되지 않고 인터프리터를 이용하여 런타임에 해석됩니다.
따라서 오류가 생길 수 있고 잘못된 문자열이 만들어질 수 있습니다.
이 규칙은 아래와 같은 클래스들의 format(...)
메소드를 사용할 때 전달인자와 포맷을 정적으로 분석하여 검증합니다.
java.util.Formatter
java.lang.String
java.io.PrintStream
MessageFormat
java.io.PrintWriter
더불어 아래와 같은 클래스들의 printf(...)
메소드를 사용할 때도 이 규칙이 사용됩니다.
java.io.PrintStream
java.io.PrintWriter
규칙을 어긴 코드
String.format("First {0} and then {1}", "foo", "bar"); //규칙을 어긴 코드. 을 사용한 것 처럼 보입니다. 하지만 여기서는 이 포맷을 사용할 수 없습니다. "foo"과 "bar"는 무시됩니다.
String.format("Display %3$d and then %d", 1, 2, 3); //규칙을 어긴 코드; '2'는 사용되지 않습니다
String.format("Too many arguments %d and %d", 1, 2, 3); //규칙을 어긴 코드; '3'가 사용되지 않습니다
String.format("First Line\n"); //규칙을 어긴 코드; 플랫폼별로 다른 개행 기호를 생성하기 위해 \n 대신 %n을 사용해야 합니다
String.format("Is myObject null ? %b", myObject); //규칙을 어긴 코드; %b에 boolean이 아닌 값이 할당되면, null이 아닌 경우 true를 반환하고 null인 경우 false를 반환합니다. 이것이 의도한 바일지라도 오해의 소지가 있는 방식입니다. 만약 의도한 바라면 차라리 myObject == null 처럼 사용하여 의도를 확실히 드러내는 것이 좋습니다.
String.format("value is " + value); // 규칙을 어긴 코드
String s = String.format("string without arguments"); // 규칙을 어긴 코드
MessageFormat.format("Result '{0}'.", value); // 규칙을 어긴 코드; 문자열에 매칭하는 파라미터 포맷이 없습니다 ('가 {0}을 무시하게 만듭니다)
MessageFormat.format("Result {0}.", value, value); // 규칙을 어긴 코드; 두번째 value가 사용되지 않습니다
MessageFormat.format("Result {0}.", myObject.toString()); // 규칙을 어긴 코드; myObject의 toString()을 호출할 필요가 없습니다
java.util.Logger logger;
logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject.toString()); // 규칙을 어긴 코드; myObject의 toString()을 호출할 필요가 없습니다
logger.log(java.util.logging.Level.SEVERE, "Result.", new Exception()); // 규칙을 준수한 코드, 파라미터로 Exception 객체를 주는 것은 괜찮습니다
logger.log(java.util.logging.Level.SEVERE, "Result '{0}'", 14); // 규칙을 어긴 코드 - 문자열에 매칭하는 파라미터 포맷이 없습니다
logger.log(java.util.logging.Level.SEVERE, "Result " + param, exception); // 규칙을 어긴 코드; 다른 문자열을 연결하고 싶다면 람다식을 사용해야합니다.
org.slf4j.Logger slf4jLog;
org.slf4j.Marker marker;
slf4jLog.debug(marker, "message {}");
slf4jLog.debug(marker, "message", 1); // 규칙을 어긴 코드 - 문자열에 매칭하는 파라미터 포맷이 없습니다
org.apache.logging.log4j.Logger log4jLog;
log4jLog.debug("message", 1); // 규칙을 어긴 코드 - 문자열에 매칭하는 파라미터 포맷이 없습니다
규칙을 준수한 해결책
String.format("First %s and then %s", "foo", "bar");
String.format("Display %2$d and then %d", 1, 3);
String.format("Too many arguments %d %d", 1, 2);
String.format("First Line%n");
String.format("Is myObject null ? %b", myObject == null);
String.format("value is %d", value);
String s = "string without arguments";
MessageFormat.format("Result {0}.", value);
MessageFormat.format("Result '{0}' = {0}", value);
MessageFormat.format("Result {0}.", myObject);
java.util.Logger logger;
logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject);
logger.log(java.util.logging.Level.SEVERE, "Result {0}'", 14);
logger.log(java.util.logging.Level.SEVERE, exception, () -> "Result " + param);
org.slf4j.Logger slf4jLog;
org.slf4j.Marker marker;
slf4jLog.debug(marker, "message {}");
slf4jLog.debug(marker, "message {}", 1);
org.apache.logging.log4j.Logger log4jLog;
log4jLog.debug("message {}", 1);
같이보면 좋은 자료
If you like SONARKUBE, don’t forget to give me a star.