개발 등/중급

String 클래스의 이모저모

darkhorizon 2008. 9. 5. 20:31
728x90
반응형
class StringTest{
    public static void main(String[] args){
        String str1="myCat";
        String str2="myCat";
        String str3=new String("myCat");
        String str4=new String("myCat");

       System.out.println("str1==str2 : "+(str1==str2));
       System.out.println("str1.equals(str2) :  "+(str1.equals(str2));
       System.out.println("str3==str4 : "+(str3==str4));
      System.out.println("str3.equals(str4) :  "+(str3.equals(str4));
       System.out.println("str1==str3 : "+(str1==str3));
      System.out.println("str1.equals(str3) :  "+(str1.equals(str3));
    }
}

위의 소스코드를 컴파일 한 후 실행하면 아래와 같은 결과값이 출력될 것이다.

str1==str2 : true
str1.equals(str2) : true
str3==str4 : false
str3.equals(str4) : true
str1==str3 : false
str1.equals(str3) : true

여기서 주목해야 할 것은 등가비교연산자인 (==)과 equals() 의 결과값이 다르다는 것이다,
오브젝트 클래스에 정의된 equals()를 보면
    public boolean equals(Object obj){
       return (this==obj);
    }
과 같다.
즉 등가비교연산자나 equals()는 모두 참조값을 비교하도록 되어 있다.
그래서 new 연산자를 사용한 객체를 비교하게 되면 동일한 클래스일지라도 결과값은 false 가 된다.
그런데 왜 유독 String 클래스에서는 true 의 결과값이 나올까?
이유는 오브젝트의 equals()를 String 클래스에서 아래와 같이 오버라이딩했기 때문이다.

    public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = offset;
        int j = anotherString.offset;
        while (n-- != 0) {
            if (v1[i++] != v2[j++])
            return false;
        }
        return true;
        }
    }
    return false;
    }

코드 분석이 어렵다면 "주소값이 같거나 또는 문자열의 내용이 동일하면 참"을 리턴하도록 오버라이딩 되어있다는 것만 알고 넘어가면 될 것 같다.
그래서 맨 위의 결과값이 모두 참으로 리턴된 것이다.

문자열은 두 가지의 방법으로 생성한다.
첫 번째는 리터럴로 생성, 두 번째는 new연산자를 이용해서 생성하는 방법이 있다.
String str1="myCat";                          => 리터럴로 생성
String str2="myCat";
String str3=new String("myCat");      => new연산자로 생성
String str4=new String("myCat");

리터럴로 생성하는 것은 Constant pool 이라는 상수 영역에 저장하는 방법이다.
이렇게 되면 이후 리터럴로 생성된 str2 는 이미 상수 영역에 생성된 문자열을 참조하게 된다.
그래서 등가비교연산자나 equals()가 모두 참이 된다.
반면 new 연산자를 사용하게 되면 새로운 String 인스턴스가 만들어진다.
그래서 str3와 str4는 다른 주소값을 가지기 때문에 등가비교연산자에서는 false가 나오게 된다.
반면에 str1, str2, str3, str4 는 모두 같은 문자열을 가지고 있기 때문에 오버라이딩된 String 클래스의 equals()에 의해 모두 true 의 결과값을 가지게 되는 것이다.
728x90