본문 바로가기
카테고리 없음

String은 참조 타입인가요?

by GGShin 2022. 5. 8.

안녕하세요! 🐥

 

오늘은 잠깐 String에 대해 이야기 해보려고 합니다. 정확히는 제가 공부를 하며 헷갈렸던 부분에 대해 이야기 해보겠습니다.

Java를 배우면 primitive type(int, long, double, ...)과 String에 대해 가장 먼저 배우게 됩니다. 데이터 활용에 기본이 되는 형태이기 때문입니다. 그런데 String은 primitive type(기본 타입)과는 다르게 class라는 사실도 알고 계셨나요?

String은 기본 타입은 아니지만 굉장히 사용 빈도가 높기 때문에 특별히 class로 제작되어 사용되는 타입입니다. 

 

Class는 reference type이기 때문에 인스턴스를 만들면 변수에는 데이터 자체가 저장되는 것이 아니라 데이터가 저장된 주소를 담게 된다는 것입니다. 그렇다면 String도 class 니까 변수를 만들면 그 변수에는 데이터의 주소를 담겠구나라는 생각이들었습니다. 그래서 당시에 한 번 테스트를 해보았습니다. 물론 며칠이 지난 후에 다시 보니 왜 이걸 헷갈렸지? 라는 의문이 들던 사항이었지만 혹시라도 저와 유사한 혼동을 하는 분이 계실까 하여서 올려봅니다!

 

먼저 reference type이 어떻게 동작하는 지 보여드리기 위해 class로 예시를 보여드리겠습니다.

아래와 같이 Test라고 하는 클래스를 정의하였고 ,

public class Test {
    private int a = 0;
    public Test() {};

    public void setA(int a) {
        this.a = a;
    }
    public int getA() {
        System.out.println(this.a);
        return this.a;
    }
}

Main class에 Test class type의 변수인 testA를 만들어 주었습니다.

그리고 참조변수 testB는 testA를 할당해 두 변수가 같은 주소를 가지도록 해주었습니다.

public class Main {

    public static void main(String[] args) {
        Test testA = new Test();
        Test testB = testA;

        testA.getA(); //Prints 0
        testB.getA(); //Prints 0

        testA.setA(100);
        testA.getA(); //Prints 100
        testB.getA(); //Prints 100
    }
}

이렇게 하니 testA를 이용해서 int a의 값을 100으로 변경했지만 testA.getA() 뿐만 아니라 testB.getA()도 같은 값을 프린트하는 것을 볼 수 있습니다. 이것은 testB에 할당된 것이 데이터 자체가 아닌 데이터의 주소이기 때문입니다. 그리고 그 주소는 testA에 할당된 주소와 일치하는 것이죠! reference type에 대해 공부를 해보셨다면 어떤 내용인지 이해가 되실 겁니다.

 

그렇다면 String도 같은 현상을 보이는 건가? 하는 궁금증이 생겼습니다. 

그래서 나름대로 한 번 테스트를 해보았는데요,

 

public class Main {

    public static void main(String[] args) {
        String str = new String("This is String");
        String str2 = str;

        System.out.println(str); //Prints This is String
        System.out.println(str2); //Prints This is String

        str = "Another String now";

        System.out.println(str); //Prints Another String now
        System.out.println(str2); //Prints This is String
    }
}

저는 이때 str = "Another String now"; 이 부분이 데이터를 수정한 것이라고 생각했었습니다. (위 class 코드에서 testA.setA(100); 을 한 것과 같은 것을 했다고 생각한 것이죠)

그래서 str2도 "Another String now"를 프린트 할 것이라고 생각했는데, 실제로 보니 변하지 않고 This is String을 프린트하길래 상당히 혼란스러웠습니다. 구글링을 해보니 4년전에 저와 같은 혼란을 겪은 분이 계셔서 도움을 받을 수 있었습니다.

 

바로 str =  "Another String now"; 라는 코드는 데이터를 변경한 게 아니라 그저 str에 새로운 문자열을 할당한 것이기 때문이었습니다. 

Class로 따지자면 아래처럼 아예 testA 참조 변수에 새로운 클래스 인스턴스를 할당한 꼴인 것입니다.

      Test testC = new Test();
      testA = testC;

그렇게 제 의문은 해결이 되었습니다..ㅎㅎ 

다시 보면 왜 헷갈렸을까 싶지만 어찌되었든 정확하게 알게되어서 다행이라고 생각합니다.

 

한 가지 새롭게 알게된 String에 대한 사실은 String은 한 번 생성이 되면 그 데이터를 변경할 수 없다(immutable)고 합니다. 

public static void main(String[] args) {
        String a = "ABC";
        a = "ABCD";
        System.out.println(a);
}

이렇게 하면 a에 초기에 저장했던 "ABC"가 "ABCD"로 바뀌는 것이 아니라

"ABC"는 폐기가 되고 "ABCD"가 새롭게 할당이 된다고 합니다.

우리가 사용할 때에는 이 차이를 크게 느낄 일은 없을 것 같지만 이런 특성이 있다고 하네요!

 

한번 String과 관련된 저의 혼란과 새롭게 알게된 사실을 적어보았습니다. 

혹시나 비슷한 궁금증이 있으셨던 분께 도움이 되었으면 좋겠습니다. 감사합니다.☺️

 

*참고 자료:

https://stackoverflow.com/questions/51466358/how-is-string-a-reference-type-in-java

 

 

How is String a reference type in Java?

I understand that classes are reference types, for example I created the following class: class Class { String s = "Hello"; public void change() { s = "Bye"; } } With the following code, I

stackoverflow.com

 

반응형