ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • java.lang 패키지 - String 클래스 속성
    백엔드/자바 2020. 8. 12. 15:41

    String 클래스

    자바를 사용하면서 가장 많이 쓰게 되는 클래스 중 하나로 C언어와 달리

     

    문자열을 쉽게 다룰 수 있게 도와주는 메서드를 가지고 있는 클래스다.

     

    String 클래스는 내부적으로 문자형 배열 참조 변수( char[] ) value로 가지고 있다.

     

    참조 변수 value는 String 인스턴스 생성시 입력하는 문자를 문자형 배열의 형태로 저장하게 된다.

     

    설명을 들어선 좀 이상하다면 아래 코드를 보도록 하자.

     

     

     

    String을 써줄 때는 위와 같은 두 가지 방식으로 선언하게 된다.(물론 첫번째가 압도적으로 많이 쓰인다.)

     

    얼핏보면 우리가 문자열을 통째로 저장하는것처럼 보인다.

     

     

     

    하지만 실제로는 위와 같이 문자형 배열의 형태로 인스턴스 변수 value에 저장이 된다.

     

    즉 우리가 String 클래스를 이용할 때 입력하는 문자열은 문자열 통째로 저장되는 것이 아니다.

     

    문자형 배열(char[])의 형태로 하나 하나 잘게 쪼개져서 저장되는 것이다.

     

    하지만 String클래스는 이러한 문자형 배열을 쓰기 쉽게 다양한 메서드를 제공하고 있으며

     

    그로 인해 우리는 C언어에 비해 자바에서 문자열을 더 쉽게 다룰 수 있게되었다.

    변경 불가능한(immutable) 클래스

    String 클래스의 가장 큰 특징 중 하나는 바로 immutable이라는 것이다.

     

    간단히 말하면 String 인스턴스가 가진 문자열은 읽어올 수만 있고 변경은 불가능하다.

     

    무슨 말이냐고? 코드로 보면서 이해해보자.

     

     

     

    위의 선언된 변수 a를 보도록 하자.

     

    a에 b를 더하고 난 뒤 변수 a는 이전의 변수 a와 같은 변수일까?

     

    얼핏보면 모두 같은 변수처럼 보인다.

     

    하지만 실제로 a는 이전의 a와는 다른 새로 생성된 인스턴스다.

     

     

     

    시스템상의 해시코드를 출력해보면 변수 a의 해시코드가 변경된 것을 볼 수 있다.

     

    즉 문자열에 변경이 가해질 경우 String 클래스는 인스턴스의 value를 변경하는 것이 아니다

     

    그냥 아예 새로운 인스턴스를 만들어서 새로운 문자열을 저장하는 것을 확인할 수 있다.

     

     

     

    그래서 문자열을 자주 변경해야하는 작업에는 String이 아닌 StringBuffer 클래스가 더 적합하다.

     

    위의 코드 StringBuffer는 문자열 변경에도 인스턴스를 새로 생성하지 않기 때문이다.

    문자열을 만드는 방법

     

    위에서 언급했듯 String클래스를 이용한 문자열을 만드는 방법은 크게 두 가지다.

     

    하나는 변수 a,b처럼 문자열 리터럴을 지정하는 것이고, 다른 하나는 c,d처럼 생성자를 이용하는 것이다.

     

     

     

    이번에는 변수 별로 해시코드를 확인해보자.

     

    그런데 변수 a, b의 해시코드가 좀 이상하다.

     

    보통 객체별로 다른 해시코드를 가진다는데 둘은 갖은 해시코드를 가진다. 왜그럴까?

     

    문자열 리터럴을 지정하는 방식으로 문자열을 만들면 이미 존재하는 문자열을 재활용하기 때문이다.

     

     

     

    대략 위의 변수들이 메모리를 사용하는 방식을 그림으로 나타내면 위와 같다.

     

    문자열 리터럴을 지정하는 방식으로 쓰면 변수들은 메모리상의 문자열을 재활용해 참조한다.

     

    그래서 해시코드값이 같을 수 밖에 없다.

     

    반면 new 생성자를 이용하면 매번 객체가 새로 생성되기 때문에 각각 다른 해시코드를 갖게 된다.

     

    조금 더 자세히 설명하면 다음과 같다.

     

     

     

    우리가 작성한 소스파일에 포함된 모든 문자열 리터럴(상수)은 컴파일시 클래스 파일에 저장된다.

     

    이때 같은 내용의 문자열 리터럴은 단 한번만 클래스 파일에 저장된다.

     

    문자열 리터럴도 String 인스턴트고, 한번 생성하면 내용을 변경할 수 없으니

     

    하나의 인스턴스를 공유하면 되기 때문이다.

     

    이 클래스파일에는 소스파일의 모든 리터럴 목록이 있고,

     

    이 목록의 리터럴들이 JVM내의 상수 저장소(Contant pool)에 저장된다.

     

    그래서 이렇게 저장된 하나의 리터럴을 위의 그림처럼 변수 a,b,c가 참조하게 된다.

     

    그래서 변수 a,b,c는 같은 해시코드 값을 갖게 되는 것이다.

    '백엔드 > 자바' 카테고리의 다른 글

    java.lang 패키지 - join ( ) , StringJoiner  (0) 2020.08.13
    java.lang 패키지 - String 클래스 메서드  (0) 2020.08.12
    java.lang 패키지 - Object 클래스  (0) 2020.08.11
    예외에서 finally 블럭  (0) 2020.08.11
    예외 선언하기  (0) 2020.08.11
Designed by Tistory.