자바 개발자들은 스트링을 다른 첫번째 클래스 객체들과는 다른 방법으로 다룬다. 'new'를 사용해서 새로운 스트링을 초기화할 수 있다.
String string = new String("hello"); //not recommended
다음의 구문을 이용해도 거의 비슷한 결과를 얻을 수 있다.
String string = "hello";
이번 팁은 '두 스트링이 동일한 경우'에 대해 설명한다. 그것들은 객체이기 때문에 equals() 메소드를 사용하여 두 스트링의 값을 비교해볼 수 있다. 만약 s1과 s2가 같은 값을 가지는 두 스트링이라면, s1.equals(s2) 은 true이다. S1과 s2를 비교하기 위해 == 를 사용하면 약간 까다로워지는데, 이번 팁에서 s1 == s2 가 true을 리턴하는 경우에 대해 알아보자.
우선 Double 타입의 객체 두 개, double 타입의 프리미티브 두 개, String 타입의 객체 두 개를 생성해보자. 그리고 String을 초기화 하기 위해 s1 = "hello" 라는 구문을 사용하자.
class Equals {
public static void main(String[] args) {
Double object1 = new Double("7.2");
Double object2 = new Double("7.2");
System.out.println
("For Double objects both 7.2");
System.out.print("\t object1 == object2 is " );
System.out.println(object1 == object2);
System.out.print("\t object1.equals(object2) is ");
System.out.println(object1.equals(object2));
double prim1 = 7.2;
double prim2 = 7.2;
System.out.println
("For double primitives both 7.2");
System.out.print("\t prim1 == prim2 is " );
System.out.println(prim1 == prim2);
String string1 = "7.2";
String string2 = "7.2";
System.out.println("For Strings both 7.2");
System.out.print("\t string1 == string2 is " );
System.out.println(string1 == string2);
System.out.print("\t string1.equals(string2) is ");
System.out.println(string1.equals(string2));
}
}
Equals 을 실행시키면, 다음과 같은 결과를 얻을 수 있다.
For Double objects both 7.2
object1 == object2 is false
object1.equals(object2) is true
For double primitives both 7.2
prim1 == prim2 is true
For Strings both 7.2
string1 == string2 is true
string1.equals(string2) is true
예상했던 대로, object 1과 object 2는 같은 값을 가지고 있기 때문에 object1.equals(object2) 는 true이지만, 서로 다른 객체이기 때문에 object1 == object2 는 false이다. 또한 prim1 == prim2 역시 같은 값을 갖기 때문에 true이다. (두 개의 프리미티브들을 비교하기 위해 equals() 을 사용할 수 없음을 주의하자.) string 1과 string 2의 경우에도 이들은 같은 값을 갖기 때문에 string1.equals(string2) 은 true이다. 아마도 string1 == string2 도 true이라는 것에 놀랄 것이다. 자바 언어의 설명서는 "같은 패키지의 같은 클래스 내에서는 정수(literal) 스트링들은 동일한 String 객체를 참조한다"라고 설명하고 있다.
또한 설명서는 "스트링 정수, 혹은 좀더 보편적으로 상수식의 값이 되는 스트링은 String.intern메소드를 사용하여 고유의 인스턴스를 공유하도록 'interned'된다."라고 설명하고 있다.
외관상으로, 다음의 예제는 객체를 초기화하듯이 스트링을 초기화하는 것과, 프리미티브를 초기화하듯이 스트링을 초기화하는 것의 차이를 강조하고 있다. 실제로는 스트링을 얻기위한 방법으로써, 스트링 정수를 직접적으로 사용하는 방법과 스트링 구성자를 호출하는 방법의 차이점을 실연한다.
class NewEquals {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = "hello";
System.out.println("For new Strings s1 and s2");
System.out.print("\t s1 == s2 is ");
if (s1 == s2)
System.out.println("true");
else
System.out.println("false");
System.out.print("\t " + "s1.equals(s2) is ");
if (s1.equals(s2))
System.out.println("true");
else
System.out.println("false");
System.out.println("For Strings s1 and s3");
System.out.print("\t s1 == s3 is ");
if (s1 == s3)
System.out.println("true");
else
System.out.println("false");
System.out.print("\t " + "s1.equals(s3) is ");
if (s1.equals(s3))
System.out.println("true");
else
System.out.println("false");
}
}
NewEquals을 실행하면, 다음과 같은 결과를 볼 수 있다.
For new Strings s1 and s2
s1 == s2 is false
s1.equals(s2) is true
For Strings s1 and s3
s1 == s3 is false
s1.equals(s3) is true
세 개의 스트링 모두 같은 값으로 생성되었기 때문에, equals() 은 두 번의 비교에서 모두 true을 리턴한다. 그러나, s1과 s2는 다른 객체이다. 같은 값으로 구성되었음에도 불구하고, 그것들은 첫 번째 예제에서 보았던 두 개의 Double 객체와 같이 서로 다르다. 이것이 s1 == s2 는 false인 이유이다. 비슷한 이유로 s1 == s3 역시도 false이다.
==연산자를 이용하여 두 개의 스트링을 비교했을 때 true를 리턴했던 첫번째 예제(Equals)가 아니었다면, 위의 결과에 놀라지 않았을 것이다. 이 객체들은 객체의 속성을 가지고 있는 것처럼 보인다. Equals 예제는 스트링을 위한 풀(pool)이 있음을 보여준다. 다중 스트링 변수들은 동일한 스트링 객체를 참조할 수 있다. 따라서 여러 개의 스트링 변수가 동일한 스트링 상수로 설정되었다면 앞서 설명한 것처럼 이를 참조하게 될 것이다.
자바 언어 설명서는 새로운 호출은 새로운 객체를 생성할 것이라고 보증한다. 그 객체는 String.intern 에 결코 속하지 않을 것이다. 그러나 스트링 상수의 값이 String.intern에 넘겨진 스트링인 경우에는 다르다. 설명서에 따르면, 사용자는 intern() 메소드를 사용하여 스트링을 일반적인 스트링 풀에 강제로 집어넣을 수 있다고 설명하고 있다. 다음 예제를 통해 살펴보자.
class NewInternString {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = "hello";
s1 = s1.intern(); //this changes everything
System.out.println("For Strings s1 and s2");
System.out.print("\t s1 == s2 is " );
if (s1 == s2)
System.out.println("true");
else System.out.println("false");
System.out.print("\t " + "s1.equals(s2) is ");
if (s1.equals(s2))
System.out.println("true");
else System.out.println("false");
System.out.println("For Strings s1 and s3");
System.out.print("\t s1 == s3 is " );
if (s1 == s3)
System.out.println("true");
else System.out.println("false");
System.out.print("\t " + "s1.equals(s3) is ");
if (s1.equals(s3))
System.out.println("true");
else System.out.println("false");
}
}
NewInternString을 실행한 결과는 다음과 같다.
For new Strings s1 and s2
s1 == s2 is false
s1.equals(s2) is true
For Strings s1 and s3
s1 == s3 is true
s1.equals(s3) is true
또다시 값이 동일하다고 나타나는 것을 볼 수 있을 것이다. 그 이유는 equals() 메소드가 두 경우 모두에서 true를 리턴하기 때문이다. s1을 강제로 상수 풀에 집어넣은 후에 s1 == s3 가 true 인 것을 알 수가 있을 것이다. 그러나 s2는 상수 풀에 속해있지 않기 때문에 s1 == s2는 false이다.
이번 팁에서는, 스트링이 같은 값을 가지고 있는지를 테스트 하는 유일하고 안전한 방법으로써 equals() 메소드를 사용하는 법을 배워보았다. 같은 값을 가지는 스트링들을 가지고 작업을 한다면, 이 방법은 상수 풀에 스트링들을 인터닝할 만한 가치가 있을 것이다. == 연산자를 사용해서 좀더 빨리 체크할 수도 있다. 하지만 어느 경우에도 등가성을 체크하기 위한 방법으로 == 의 사용을 결정하기 전에 신중해야만 한다는 것을 알 수 있다.
스트링 비교에 관한 더 많은 정보는 Arnold, Gosling, 그리고 Holmes가 쓴 Java Programming Language 3판의 섹션 9.2 "String Comparisons"를 참고하기 바란다.
"Java SE" 카테고리의 다른 글
- JSSE 이용한 안전한 커뮤니케이션 (댓글 2개 / 트랙백 0개) 2004/08/31
- 3D 화면(scene)에 빛 효과 주기 (댓글 1개 / 트랙백 0개) 2004/07/30
- Java SE & Java SE for Business 지원 로드맵 (댓글 0개 / 트랙백 0개) 2009/09/11
- 클래스에서 enhanced For-Loop 사용 (댓글 0개 / 트랙백 1개) 2007/10/09
- VARIABLE CONTENT로 메세지 포맷하기 (댓글 7개 / 트랙백 2개) 2003/08/19
- CONTENTPANE 작업의 변화 (댓글 1개 / 트랙백 0개) 2004/11/11
- 새로운 포매터로 출력물 포맷하기 (댓글 1개 / 트랙백 0개) 2004/10/27
- 스윙 유저 인터페이스에서 컴포넌트의 방향성 (댓글 2개 / 트랙백 0개) 2003/09/26
- 쓰레드의 상태정보를 저장할 때 사용되는 THREADLOCAL 변수들 (댓글 4개 / 트랙백 0개) 2003/12/12
- 2개의 스트링이 같은 경우는? (댓글 2개 / 트랙백 0개) 2004/05/27
댓글을 달아 주세요
스트링 관련 정보는 어떤 랭귀지라도 매우 중요하다고 생각되는데.
2007/09/14 21:07그런 차원에서 느끼기에..매우 좋은 정보인것같습니다.
좋은 정보 감사해요~
2007/09/19 05:46