쌓고 쌓다

[JAVA] String 클래스 [ hashCode()와 identityHashCode() ] 본문

프로그래밍/java

[JAVA] String 클래스 [ hashCode()와 identityHashCode() ]

승민아 2022. 5. 21. 21:45

String -> java.lang.String

String 생성자

String() 빈 스트링 객체 생성
String(char[] c) char 배열에 있는 문자들을 스트링 객체로 생성
String(String str) 매개변수로 주어진 문자열과 동일한 스트링 객체 생성
String(StringBuffer buffer) 매개변수로 주어진 스트링 버퍼의 문자열로 객체 생성

 

생성자 예제 코드

public class Hongong {

    public static void main(String args[]){

        char[] c = {'a', 'b', 'c', 'd'};

        String str1="abcd";
        String str2=new String(c);
        String str3=new String("abcd");

        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);

    }
}

 

실행 결과

 

스트링 리터럴과 new String()

1. 스트링 리터럴 -> "abcd"

  • 자바 가상 기계 내부에서 리터럴 테이블(정적 메모리)에 저장되고 관리됨.
  • 응용프로그램에서 공유됨.

스트링 리터럴 예제 코드

public class Hongong {

    public static void main(String args[]){

        String a = "Hello";
        String b = "Java";
        String c = "Hello";
        System.out.println(a.hashCode());
        System.out.println(b.hashCode());
        System.out.println(c.hashCode());
    }
}

 

실행 결과

실제로 같은 해시코드 값을 가짐

2. new String() -> new String("abcd")

  • new String()으로 생성된 스트링
  • 이 스트링 객체는 힙에 생성되며 공유되지 않음

 

new String() 예제 코드

public class Hongong {

    public static void main(String args[]){

        String d = new String("Hello");
        String e = new String("Java");
        String f = new String("Hello");
        System.out.println(d.hashCode());
        System.out.println(e.hashCode());
        System.out.println(f.hashCode());
        /*System.out.println();
        System.out.println(System.identityHashCode(d));
        System.out.println(System.identityHashCode(e));
        System.out.println(System.identityHashCode(f));*/
    }
}

 

실행 결과

 

아니 왜! 위의 설명과 달리

hashCode()로 같은 값이 출력이 되는 걸까?

 

사실 String의 hashCode()는 아래와 같이 오버 라이딩이 되어있다.

이 hashCode()의 반환 값이 어떻게 나왔냐 하면

s[0]*31^(n-1) + s[1]*31^(n-2) * .... + s[n-1]의 형태로 나온다.

즉. 아스키 코드를 이용해 값을 만들기에 똑같은 문자열인 경우, 같은 값을 반환하는 것이다.

 

따라서 public static int System.identityHashCode(Object x) 로 값을 확인하자

이 identityHashCode()는 객체의 고유한 hashCode 값을 리턴한다.

이것은 static이라 오버 라이딩이 불가하기에 원하는 값을 출력할 수 있다.

 

수정된 주소 값 확인 예제

public class Hongong {

    public static void main(String args[]){

        String d = new String("Hello");
        String e = new String("Java");
        String f = new String("Hello");
        System.out.println(d.hashCode());
        System.out.println(e.hashCode());
        System.out.println(f.hashCode());
        System.out.println();
        System.out.println(System.identityHashCode(d));
        System.out.println(System.identityHashCode(e));
        System.out.println(System.identityHashCode(f));
    }
}

 

실행 결과

똑같은 hashCode의 결과를 나타내지만 아래의 출력물은 다른 값을 갖는 것을 볼 수 있다.

사실 첫 번째로 스트링 리터럴의 주소 값도 이런 식으로 확인했어야 했다.

 

스트링 객체의 주요 특징

  • 스트링 객체는 수정 불가능하다. ( 레퍼런스는 바꿀 수 있음 )

 

String 주요 메소드

메소드 설명
char charAt(int index) 해당 인덱스의 문자 값 리턴
... 해당 인덱스에 있는 유니코드 값 리턴
int compareTo(String anotherString) 두 스트링이 같으면 0, another이 더 클때 음수,
another이 더 작으면 양수 반환
String concat(String str) str 스트링을 현재 스트링 뒤에 덧붙인 문자열 반환
boolean contains(Charsequence s) s의 문자를 포함하고 있으면 true 리턴
int length() 스트링의 길이 반환
String replace(CharSequence target, CharSequence replacement) target 문자를 replacement 문자로 바꾸고 반환
String[] split(String regex) regex와 일치하는 문자들을 기준으로 분리된 스트링을 배열에 저장하여 리턴
String subString(int beginIndex) 해당 인덱스부터 시작하는 서브 스트링 리턴
String toLowerCase() 소문자로 바꾼 스트링 리턴
String toUpperCase() 대문자로 바꾼 스트링 리턴
String trim() 스트링 앞뒤의 공백을 제거한 스트링 반환

 

String trim()

public class Hongong {

    public static void main(String args[]){
        String a = "          ABCD\t";
        System.out.print(a.trim());
    }
}

스트링 앞뒤에 있는 공백제거(\t 또한 제거됨)

 

compareTo()

public class Hongong {

    public static void main(String args[]){
        String java="java";
        String cpp="C++";
        System.out.println(java.compareTo(cpp));
    }
}

java가 C++보다 뒤에 오기에 java-cpp는 양수가 나옴

 

종합 예제 코드

public class Hongong {

    public static void main(String args[]){
        String a=" C#";
        String b=",C++";

        System.out.println(a.length());
        System.out.println(a.contains("#"));

        a=a.concat(b);
        System.out.println(a);

        a=a.trim();
        System.out.println(a);

        a=a.replace("C#","Java");
        System.out.println(a);

        String s[] = a.split(",");
        for(int i=0;i<s.length;i++)
            System.out.println("분리된 문자열"+i+": "+s[i]);

        a=a.substring(5);
        System.out.println(a);

        char c = a.charAt(2);
        System.out.println(c);
    }
}

 

실행 결과

'프로그래밍 > java' 카테고리의 다른 글

[JAVA] StringToKenizer 클래스  (0) 2022.05.22
[JAVA] StringBuffer 클래스  (0) 2022.05.22
[JAVA] Wrapper 클래스  (0) 2022.05.21
[JAVA] Object 클래스  (0) 2022.05.21
[JAVA] 명품 자바 프로그래밍 5장 실습문제  (0) 2022.05.18
Comments