프로그래밍/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());
}
}
compareTo()
public class Hongong {
public static void main(String args[]){
String java="java";
String cpp="C++";
System.out.println(java.compareTo(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);
}
}
실행 결과