자바에서의 개행 📃
본인은 보통 자바의 문자열 내에서 라인을 개행할 때 아래와 같이 개행하곤 했다.
System.out.println("안녕하세요\\n");
그러던 중, 조원과의 대화를 통해 놓치고 있던 부분에 대한 하나의 인사이트를 얻게 되었다.
그건 바로 개행 문자는 OS별로 상이하다는 점이다.
이전에 대학 강의에서 배웠던 것이 어렴풋이 기억이 나긴 하지만 정확히는 기억이 나질 않아 찾아보았고
그 결과 개행 문자가 3종류나 존재하고 있으며, OS 별로 상이한 경우도 존재함을 알 수 있었다.
개행문자 종류
CRLF(\r\n), CR(\r), LF(\n)
- Windows 운영체제: CRLF(\r\n)
- Unix 계열: LF(\n)
- Mac: CR(\r)
- 이후 Macintosh: LF(\n)
🧐 그럼 \n 없이 어떻게 구현할까?
처음 생각했던 방법은 System.out.println();을 한 번 더 호출해주는 방법이다.
System.out.println("안녕하세요");
System.out.println();
이렇게 말이다.
그럼 이제 문제가 없지 않을까?
🔥 절대 그렇지 않다.
🙌 System.out.println()
System.out.println() 메서드의 내부를 살펴보면, 다음과 같이 newLine()을 호출하고 있는 것을 알 수 있다.
그리고 이 newLine()이 말하고자 하는 문제의 원인이다.
newLine() 을 살펴보면 위와 같이 synchronized 키워드를 사용하고 있음을 알 수 있는데,
synchronized 키워드는 동기를 뜻하며 newLine을 호출하는 하나의 스레드가 작업이 끝날 때 까지 해당 메서드에 묶여있어야 한다는 뜻이다.
😗 이렇게 되는 경우 여러 스레드가 newLine() 메서드를 실행하려고 한다면,
block 현상이 발생할 수 있어 성능 상의 문제를 야기할 수 있다.
조원을 통해 알게 된 lineSeperator() ✂️
우테코에서 사다리 미션을 구현하면서, 조원을 통해 System.lineSeperator()라는 것을 알게 되었다.
System.lineSeperator() 는 newLine()의 내부로 더 타고 들어가면 존재하고 있는 개행 문자를 의미한다.
lineSeparator() 를 살펴보면
💬 System으로부터 독립적인 개행 문자를 return한다
라고 쓰여있다.
이러한 lineSeparator()를 사용함으로서 특정 OS 종속되지 않고 개행 문자를 사용할 수 있다.
개선된 코드 ♻️
System.out.println("안녕하세요" + System.lineSeparator());
- 이렇게 문자열에 “\\n” 등의 개행 문자가 아닌 lineSeparator()를 사용함으로서 안전한 개행이 가능해졌다.
또 다른 방법 (%n) ✨
`System.lineSeparator()` 는 사용할 때, 조금 길다는 생각이 들기도 한다.
운영체제에 맞게 알아서 개행을 도와주는 방법으로는, 또 다른 방식이 존재하는데
바로 `%n` 이다.
`%n 문자`는 자바의 출력 형식 중 개행을 뜻하며 운영체제에 맞게 알아서 개행을 해준다고 한다.
자바에서 출력 형식을 지정해서 문자열을 출력할 수 있도록 돕는
System.out.printf() 또는 String.format() 메서드와 함께 사용하여
안전한 개행을 수행할 수 있다.
변경된 코드 ♻️
System.out.println(String.format("안녕하세요%n"));
// 또는
System.out.printf("안녕하세요%n");
- 이렇게 lineSeparator()가 아닌 `%n`을 사용하더라도 안전한 개행이 가능했다.
느낀 점 💡
확실히 공부하다보면 로우 레벨까지 타고 들어가야 이해가 잘 되는 상황이 많은데,
요즘 우테코 미션을 수행하며 생겨나는 궁금증에 의해 자바의 로우 레벨 코드를 살펴보다보면 제대로 읽히지 않아 아직 부족함이 많음을 느끼곤 한다.
최근 읽고 있는 객체지향의 사실과 오해를 완독하면 자바 관련 서적을 정독하면서 자바에 대해 조금 더 깊이 있는 이해를 가지기 위해 노력해보고자 한다.
'Language > Java' 카테고리의 다른 글
[Java] Fluent API란? (feat. JDBC에 적용해보기) (0) | 2024.04.04 |
---|---|
[Java] 생성자 체이닝(Constructor Chaining) 기법 (0) | 2024.04.02 |
[Java] 클래스 멤버는 각자의 위치가 존재한다 (0) | 2024.02.28 |
[Java] LinkedHashMap을 통한 기초 캐싱 (0) | 2024.02.25 |
[Java] @NotBlank, @NotNull, @NotEmpty 차이 (1) | 2023.06.12 |