Skip to content

더 좋은 것의 기준 - Java의 1대 제자가 되어보자

글 요약

  1. Java Document를 구글링할 때 java [버전] [찾고자 하는 정보] documentation으로 검색하기

  2. VSCode에서 JDK 내부구조를 확인하기 위해선 아래와 같이 진행

    • Extention Pack for Java 설치
    • Ctrl + T로 알고 싶은 class 입력 후 Enter
    • 해당 jdk class 파일 내에 있는 소스코드 확인

🧐 이런 기준은 어디서 나온 것일까?

문자열을 저장하는 Java API를 선택할 때

String 객체보다 StringBuilder가 좋아요 StringBuilder보다 StringBuffer가 좋아요

자바를 처음 공부하면 어떤 객체가 문자를 저장하는지 그 객체를 어떻게 활용할 것인지 먼저 공부하게 되는데요. 어느 순간 다른 사람들의 소스코드를 보면 문자열을 저장할 수 있는 객체를 다양하게 사용하는 것을 알게 되었습니다.

물론 일반 자바를 공부하는 강좌나, 책에서도 볼 수 있는데요. 그렇다면 강사님과 저자들은 어떻게 이러한 기준을 알게 되었을까요?

📚 모든 것의 기준 Documentation

모든 제품에는 설명서가 존재합니다. 만든이의 의도가 무엇인지, 어떻게 사용하는지 상세히 나타나 있습니다. 프로그래밍 언어도 예외는 아니죠.

사용자들이 잘 사용할 수 있도록 그리고, 더 많은 사용자들이 올바르게 사용할 수 있도록 휼륭한 개발자들은 만든 프로그램에 대해 문서화를 합니다. 문서화를 하지 않는 프로그램은 사용하기도 어렵고, 개발자의 의도대로 사용하지 않을 가능성이 높아집니다.

그렇다면, 모든 사람들이 Documentation을 읽으면 되지 않을까? 생각하실 수도 있겠네요. 맞습니다. 프로그램을 공부하기 위해선 제일 먼저 해야 할 일은 Documentation을 읽어야 하죠. 그렇지만, Documentation은 양이 무척 방대하여, 내가 원하는 프로그램을 만들기 위한 자료를 찾지 못할 확률이 존재합니다. 따라서, Documentation은 좀 더 깊고 올바르게 이해하기 위해 사용해야 한다고 생각합니다.

🔙 다시 처음 문제로 돌아가서..

🔎 Google에 공식 문서 찾아보기

String, StringBuilder, StringBuffer의 차이점을 알기 위해서는 Java Documentation을 찾아봐야 합니다. 자신이 사용하고 있는 Java 버전을 확인한 뒤에1, 구글 검색창에 java [버전] String documentation으로 검색하면 https://docs.oracle.com 홈페이지가 나타나게 됩니다. 이 문서를 클릭해 봅시다.

Image title

이미지 1 - Java 17 Document 찾기

👀 Java Documentation 살펴보기

String Class 알아보기

String에 대한 Documentation을 살펴보면 String 클래스에 대해 어떤 특성이 있는지 확인할 수 있습니다. 아래의 이미지를 통해 큰 따옴표로("")로 작성한 상수는 전부 String class 이며, 모든 String 객체는 상수(Constant)의 성질을 가지고 있다, 정의한 객체 자체가 변할 수 있는(mutable) 것은 String Buffer이다, String 객체의 성질은 변하지 않음(immutable) 이다라는 힌트와 정보를 얻을 수 있게 됩니다.

Image title

이미지 2 - String Documentation 개요

String Buffer에 대한 정보는 어떻게 알 수 있을까요? 문서 내에 See Also를 살펴보면 String과 연관된 힌트를 얻을 수 있고, 그 안에 StringBuffer에 대한 문서의 링크를 찾아 볼 수 있습니다.

Image title

이미지 3 - String 클래스의 See Also

StringBuffer Class 알아보기

아래는 StringBuffer에 대한 설명입니다. mutable(변화가 가능) 하며, thread에 안전하다고 나타나 있습니다.

Image title

이미지 4 - StringBuffer Documentation 개요

StringBuffer의 문서를 조금 더 살펴보면, StringBuilder는 싱글 스레드에서 StringBuffer보다 빠르며 같은 기능을 가진다고 나타나에 있습니다. 이로서 어느정도 String, StringBuffer, StringBuilder에 대해 차이점을 알 수 있었습니다.

Image title

이미지 5 - StringBuffer 문서 안 StringBuilder에 대한 힌트

📋 Java Document를 통해 알 수 있는 사실

Documentation을 보고 알 수 있는 사실을 통해 문자열을 다루는 클래스를 정리하자면 아래와 같습니다.

특징 / 클래스명 String StringBuffer StringBuilder
변경 가능 여부 immutable mutable mutable
thread 적합 성 ? thread에 안전하다 single-thread에 안전하다

더 접근할 수록 immutable과 mutable의 차이는 무엇인지, immutable이 thread에 적합한지2, thread의 안전성은 어떤 기준인지, StringBuilder는 single-thread에 왜 적합한지 궁금증이 생기게 됩니다.

🚩 Documentation은 올바르게 사용할 수 있게 도와줍니다.

Documentaion은 String 클래스 예제 처럼 올바른 사용법을 알게 해주고, 자기가 몰랐던 추가적으로 고려해야 할 사항들(immutable, mutable 등)에 대한 추가 힌트를 얻을 수 있습니다. 그러나, 문서의 양이 방대하고, 처음 프로그래밍 언어를 접할 때는 접근하기에는 기초 지식을 요구하여 읽을 때 시간이 오래 걸리는 단점이 있다고 생각합니다.

🩻 JDK 뜯어보기

Visual Studio Code는 우리가 타이핑을 할 때, 클래스의 정보들에 대해 아래와 같이 힌트를 보여줍니다. 이러한 힌트는 어떻게 가져오는지 살펴보겠습니다.

❓ Integer valueOf가 왜 특정 조건에서 참조 변수가 아닐까?

Wrapper 클래스란 기본 자료형(Primitives)인 저장하여 감싸(Wrap)는 객체입니다. 기본 자료형 int,char,float,boolean 과 대응하여 Integer, Character, Float, Boolean으로 만들 수 있습니다.

Intger 객체는 new 또는 valueOf를 통해 객체를 생성할 수 있습니다. valueOf를 통해 생성한 객체는 참조 변수가 아닌 로컬 변수로 저장되어 불필요한 메모리 공간 할당을 방지할 수 있습니다.

여기서 문제는, valueOf로 생성한 값의 범위가 일정 값 이상이 되면, 이는 참조 변수로 저장이 되어 같은 객체로 인식하지 않습니다.

valueOf 예제
jshell> Integer number1 = Integer.valueOf(5);
number1 ==> 5

jshell> Integer number2 = Integer.valueOf(5);
number2 ==> 5

jshell> number1 == number2
$11 ==> true

jshell> Integer number3 = Integer.valueOf(1234);
number3 ==> 1234

jshell> Integer number4 = Integer.valueOf(1234);
number4 ==> 1234

jshell> number3 == number4
$14 ==> false

알 수 있는 한가지 사실은 Integer 객체끼리 비교할 때는 == 과 같은 연산자를 사용 할 수는 없을 것 같습니다. 왜 이런 일이 발생하게 될까요?

🔎 Java Documentation 살펴보기

Java Documentation의 Intger 클래스의 valueOf 함수를 살펴보면, -128 ~ +127 범위로 객체를 생성하게 되면 해당 범위 안에 이미 만들어진 cache가 할당 받게 되는 규칙이 있다고 합니다.

Image title

이미지 6 - Java Documentation Intger.valueOf

이 부분에 대해서 좀더 명확하게 알기 위해 VSCode에 있는 기능을 사용하여 JDK 안에 있는 Integer.valueOf의 정의 부분을 살펴보겠습니다.

🩺 VSCode 에서 Integer 클래스 구조 보기

JDK를 뜯어보기 위해 Extention에서 Extention Pack for Java를 설치한 후 Ctrl + T를 누르면 jdk의 모든 클래스와 메소드를 살펴볼 수 있는 검색창3이 나타나게 됩니다.

Image title

이미지 7 - VSCode의 Symbol 검색창

Intger 클래스 안에서 valueOf를 보면 삼항 연산자를 통해 범위 내의 값이 아니면 new를 통해 객체를 할당하는 모습을 볼 수 있습니다.

Image title

이미지 8 - valueOf의 내부구조

비록, IntegerCache에 대한 내부 구조까지 들어가진 않았지만, valueOf가 128 이상의 값으로 할당되면 new Intger(i)를 통해 할당됨을 알 수 있었습니다.

참고 - IntegerCache 에서 128까지 값을 할당하는 구조 확인

IntegerCache 내부 구조를 살펴보면, 12줄에 나와 있는 것처럼 new Integer로 해당 값들을 미리 세팅하는 것을 확인할 수 있습니다.

이로서 -128 ~ +127 범위 내에 있는 Integer 변수도, Heap에 미리 할당되어 있는 참조 변수임을 확인했습니다.

Integer$IntegerCache.class
class Integer$IntegerCache {
    // (...중략...)
        high = h;
        CDS.initializeFromArchive(Integer$IntegerCache.class);
        int size = high - -128 + 1;
        if (archivedCache == null || size > archivedCache.length) {
            Integer[] c = new Integer[size];
            int j = -128;

            for(int i = 0; i < c.length; ++i) {
                c[i] = new Integer(j++);
            }

            archivedCache = c;
        }
    // (...중략...)
}



  1. 명령 프롬프트 창을 열어서 java --version을 쓰면 확인할 수 있습니다. 

  2. 이 부분은 immutable Object에 대한 Java documentation을 찾아본 결과 변경이 불가능하기 때문에 데이터 변경에 안전하다는 답변을 받을 수 있었습니다. 

  3. 해당 검색창은 Ctrl + Shift + P 를 입력하여 'Go to Symbol in Workspace'로 들어가서 확인할 수도 있습니다. 

Comments