[JAVA 문법] String 파보기 1 (생성, 비교)

su_y2on·2022년 3월 22일
1

JAVA

목록 보기
8/14
post-thumbnail

String 파보기

C, Python, C++... 여러 언어를 다루다보면 비슷한 점들이 많아서 금방 다른언어도 빨리 배우게 됩니다.. 그렇게 가벼운 마음으로 JAVA를 시작했지만.. 자료형부터 혼돈의 카오스를 겪으며 굉장히 당황스럽더라구요ㅎㅎ;; 매번 그때그때 슥 찾아보고 이해하고 넘어갔지만 다시돌아오면 또 헷갈리는게 Java 자료형들인 것같아요 그래서 제대로 정리해두려고 합니다!! 먼저 보이는 것은 빙산의 일각이었던 까도까도 뭐가 나오는 양파같은 String을 알아보겠습니다




String만드는 두가지 방법

string은 아래처럼 두 가지 방법으로 만들 수 있습니다. 그리고 각각의 방식은 큰 차이가 있습니다.

객체방식

첫 번째로 객체방식은 아래처럼 string변수를 만듭니다. 이때 s3이라는 변수는 stack에 저장되고 "hello"는 heap영역에 저장됩니다. 그리고 그 주소가 s3변수에 저장이 됩니다. 즉 str변수에는 "hello"가 저장된 heap영역에 주소가 저장되는 것입니다.

String s3 = new String("hello"); //객체 



리터럴방식

두 번째로 리터럴방식은 아래처럼 바로 문자열을 넘겨주면 됩니다. 이때 s1은 stack에 저장되고 "hello"는 heap영역에 있는 String Constant Pool라는 별도의 공간에 들어갑니다. 그리고 그 주소가 s1변수에 저장됩니다.

String Constant Pool은 같은 값의 문자열("hello")이 들어오면 cache에서 해당 주소를 찾아줍니다. 결국 같은 문자열은 같은 주소를 가리키게 되는 것입니다.

이렇게 되는 이유는 Constant Pool에서는 HashMap의 형태로 문자열의 주소가 관리되기 때문에 같은 문자열을 여러개 저장할 필요가 없어집니다. 메모리를 아낄 수 있겠죠?

String s1 = "hello"; // 리터럴 
String s2 = "heㅣlo";









String 비교


동등연산자(==)

변수가 담고있는 값을 비교합니다. 이렇게만 보면 아 변수의 주소가 아니라 값을 비교한다는 거구나 라고 착각을 할 수도 있지만 잘 생각해보면 지금 String변수들에는 문자열이 저장되어있는 공간(heap)에 주소가 담겨있습니다!!!

따라서 리터럴방식과 객체방식으로 각각 생성해낸 문자열들을 동등비교해보면 String Constant Pool때문에 리터럴방식같은 주소를 갖기때문에 true가 나오고 객체로 만들어진 문자열은 매번 다른 공간에 할당되기 때문에 주소가 달라서 false가 나옵니다

String str1 = "hello";
String str2 = "hello";
String str3 = new String("hello");
String str4 = new String("hello");

System.out.println(str1 == str2);  //true
System.out.println(str3 == str4); //false




비교함수(equals)

equals()는 Object에 정의된 메소드로 모든 클래스가 최상위 클래스인 Object를 상속받기 때문에 별도의 정의없이 사용할 수 있습니다.(필요에의해 재정의 해도됩니다) equals도 결국에는 ==로 연산을 하기때문에 이 equals를 쓰면 ==와 별반 다르지 않습니다.

public boolean equals(Object obj) {
        return (this == obj);
    }



근데 String.java를 보면 Object의 equals를 재정의해서 아래와 같이 쓰게됩니다. 변수에 있는 주소로 가서 그 값을 비교합니다. 즉 진짜 문자열의 값을 비교할 수 있게 됩니다.

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            if (coder() == aString.coder()) {
                return isLatin1() ? StringLatin1.equals(value, aString.value)
                                  : StringUTF16.equals(value, aString.value);
            }
        }
        return false;
    }



이번에는 모두 "hello"로 true가 출력됩니다.

String str1 = "hello";
String str2 = "hello";
String str3 = new String("hello");
String str4 = new String("hello");

System.out.println(str1.equals(str2)); // true
System.out.println(str3.equals(str4)); // true

0개의 댓글