티스토리 뷰

포스팅에 앞서 내용이 틀릴 수 있습니다.
해당 부분 지적 감사히 받습니다.
 
자바의 String Class에서 알아보자.
 
자바에는 여러 가지 기본 타입이 있다.
 
String, int, double, float, char 등이 이에 속한다.
 
근데 String만 첫 문자가 대문자이다.
 
왜 그럴까?
 
관례상 자바는 Class명을 부여할 때 첫 글자를 대문자로 사용한다.
 
사실 String은 Class이다.
 
자바에서 String Class를 제공한다.
 
이를 통해 우리는 String 타입의 객체를 사용할 수 있었던 것이다.
 
마찬가지로 String은 객체였던 것이고, String str = new String("Hello"); 와 같이 선언하면 str에는 객체의 참조값이 들어가게 되는 것이다.
 
다른 언어에서는 문자열을 비교할 때 그냥 ==을 사용해서 비교했었다.
 
하지만 자바에서는 아래와 같이 비교한다.
 

String str = new String("문자열");
if(str != null && str.equals("문자열"))

 
이제 왜 그런지 알 수 있다.
 
일단 str은 값이 아니라 참조값을 저장하는 변수이기 때문에, null일 경우 참조하는 것이 없다.
 
참조값의 여부를 확인한 후 equals()라는 함수를 사용해 문자열 비교를 한다.
 
자 그런데 여기에서 어제 말했던 문제가 나온다.

String name1 = "aaa";
equals();
name1.equals();

 
equals()가 두 번 쓰인 것을 볼 수 있다.
 
하지만 위 equals()와 아래 equals()의 기능은 굉장히 다르다.
 
왜 그럴까?
 
자바의 기본기를 떠올려 보자.
 
우리는 힙영역에 생성된 인스턴스에 접근할 때, 객체의 타입부터 상위로 탐색한다고 하였었다.
 
위 equals()는 아무 객체 타입이 없이 실행된다. (물론 위와 같은 코드 상태에선 기능적으로 동작 안 함)
 
하지만 아래 name1.equals()는 name1의 객체 타입이 String이기 때문에, Object를 상속받은 String Class의 오버라이딩 된 equals() 호출한다.
 
둘의 차이를 알아보자.
 
Object Class의 equals()

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

 
 
String Class의 equals()

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

 
 
(내가 작성한 코드가 아니라 자바에서 기본 제공해 주는 메서드이다.)
 
Object에서는 단순히 현재 객체와 매개변수로 들어온 객체의 주솟값을 비교한 결과를 return 해준다.
 
String에서는 현재 객체와 매개변수 객체의 참조값이 같으면 true를 반환해 주고
 
참조값이 다르지만 객체가 String 타입일 경우(물론 String을 부모로 삼는 다른 자바의 기본 Class들도 포함된다)에는 문자열을 돌며 모두 같을 경우 true를 반환해 주는 로직이 들어가 있다.
 
이를 통해 단순 참조값 비교가 아닌 동등성을 비교하여 준다.
 
 
동일성과 동등성에 대해 간단히 용어정리를 해보자.

- 동일성 : 물리적으로 같은지(참조값)
- 동등성 : 논리적으로 같은지(들어있는 값)

 
따라서 아래와 같은 결과가 나온다.
 
코드

public static void main(String[] args) {

    String name3 = new String("ysk");
    String name4 = new String("ysk");

    System.out.println("동일성 : " + (name3 == name4)); // Object의 equals() 와 결과 같음
    System.out.println("동등성 : " +name3.equals(name4)); // String의 equals() 호출
}

 
실행 결과

 
 

(name3 == name4)

주솟값을 비교하며, 객체가 다르기 때문에 힙영역에 생성된 인스턴스 주솟값이 다르다. 동일성을 비교한다.
따라서 false를 출력한다.
 

name3.equals(name4)

논리적인 값을 비교하며, String타입을 물고 들어가기 때문에 String Class에 오버라이딩된 equals() 코드를 타며 동등성을 비교한다.
결과 true
 

댓글