들어가며
자바에서는 String이라는
이름의 클래스를 정의하여
제공하고 있다.
그리고 이 클래스의 목적은
문자열 표현에 있다.
지금까지 인식하지 못했지만
앞서 보아온 모든 예제에서
String 클래스의 인스턴스를
생성해왔다.
String 클래스의 인스턴스 생성
문자열 표현을 위한 String
인스턴스의 생성 방법은
다음과 같다.
일반적인 인스턴스 생성 방법과
차이가 없다.
String str = new String("Simple String");
이렇게 인스턴스가 생성되면,
str이 참조하는 String 인스턴스의
내부에는
문자열 "Simple String"이
담기게 되고,
이는 다음과 같이 출력하여
그 내용을 확인할 수 있다.
System.out.println(str);
지금까지 많이 호출해왔던
System.out.println 메소드는
다음과 같이 정의되어 있기
때문에
String 인스턴스의 참조 값이
인자로 전달 가능하다.
public void println(String str){ . . . }
그리고 다음과 같은 방법으로도
String 인스턴스를 생성할 수 있으며,
이것이 new를 이용한 방법보다
보편적인 String 인스턴스의 생성
방법이다.
String str = "Simple String";
이렇듯 큰따옴표를 이용하여
문자열을 표현하면,
이는 String 인스턴스의 생성으로
이어진다.
그럼 이와 관련하여 다음 예제를
보자.
class StringInst{
public static void showString(String str){
System.out.println(str);
System.out.println(str.length());
}
public static void main(String[] args){
String str1 = new String("Simple String");
String str2 = "The Best String";
System.out.println(str1);
System.out.println(str1.length()); // length의 반환 값을 인자로 전달
System.out.println(); // 단순히 '개행'이 이뤄진다.
System.out.println(str2);
System.out.println(str2.length());
System.out.println();
showString("Temp String");
}
}
/*
Simple String
13
The Best String
15
Temp String
11
*/
예제에서는 다음 두 가지의
String 인스턴스 생성 방법을
보였다.
String str1 = new String("Simple String");
String str2 = "The Best String";
그리고 String 클래스에서
다음과 같이 정의된 length
메소드를 호출하여
문자열의 길이를 반환하고,
이를 출력하였다.
public int length() { . . . } // 문자열의 길이를 반환한다.
그런데 이 상황에서 다음과
같은 의문이 든다.
위 예제에서 length의 반환
값을
println의 인자로 전달했기
때문이다.
메소드 length의 반환 값이 어떻게 println 메소드의 인자가 될 수 있는가?
메소드 println은 다음과 같이
오버로딩이 되어 있기 때문에
가능하다.
특히 인자를 전달하지 않고도
호출이 가능한데,
이럴 경우 단순히 개행을 하게
된다.
void println() { . . . }
void println(int x) { . . . }
void println(String x) { . . . }
사실 println 메소드는 보다
다양한 인자를 전달받을 수
있도록 오버로딩 되어 있는데,
여기서는 예제에서 호출한
메소드를 대상으로만
오버로딩 관계를 소개하였다.
그리고 이어서 예제의 다음
문장을 관찰할 필요가 있다.
이는 마치 문자열을 통째로
전달하는 듯한 모습을 보인다.
그러나 메소드에는 문자열이
아닌 "Temp String"을 대상으로
만들어진
String 인스턴스의 참조 값이
전달된다.
showString("Temp String");
위의 문장이 실행되면 일단
"Temp String"을 대상으로
String 인스턴스가 만들어진다.
그리고 이어서 이 인스턴스의
참조 값이 문자열 선언을
대신하게 된다.
예를 들어서 위의 문자열 선언을
통해 생성된
인스턴스의 참조값이 0x1234라고
하면,
위의 문장은 메소드 호출 전
(String 인스턴스 생성 후)
다음과 같은 상황에 놓이게 된다.
showString("Temp String");
// → showString(0x1234); // 0x1234는 인스턴스의 참조 값이라 가정
그래서 다음과 같이 매개변수
선언이 String형 참조 변수로
선언된 메소드는
문자열을 인자로 전달받을
수 있다.
public static void showString(String str) { . . . }
큰따옴표로 묶인 문자열
선언만으로도
String 인스턴스가 생성된다고
하였는데,
이 부분이 의심스럽다면 다음
두 문장의 실행을 통해서
인스턴스의 생성을 직접 확인할
수도 있다.
public static void main(String[] args){
int len = "123".length();
System.out.println(len);
}
문자열 "123"을 대상으로 메소드
length를 호출하고 있다.
문자열 "123"이 인스턴스의
생성으로 이어지지 않으면
이러한 메소드의 호출은
불가능한 일이다.
문자열 생성을 위한 두 가지 방법의 차이점
문자열 정보를 담고 있는
String 인스턴스의 생성
방법에는
다음과 같이 두 가지가
있음을 설명하였다.
String str1 = new String("Simple String");
String str2 = "The Best String";
그렇다면 이 두 방법으로
생성된 인스턴스 사이에는
어떠한 차이가 있는가?
약간의 차이가 있는데 이는
다음 예제를 통해서 보이겠다.
class ImmutableString{
public static void main(String[] args){
String str1 = "Simple String";
String str2 = "Simple String";
String str3 = new String("Simple String");
String str4 = new String("Simple String");
if(str1 == str2)
System.out.println("str1과 str2는 동일 인스턴스 참조");
else
System.out.println("str1과 str2는 다른 인스턴스 참조");
if(str3 == str4)
System.out.println("str3과 str4는 동일 인스턴스 참조");
else
System.out.println("str3과 str4는 다른 인스턴스 참조");
}
}
/*
실행 결과
str1과 str2는 동일 인스턴스 참조
str3과 str4는 다른 인스턴스 참조
*/
참조변수를 대상으로 한 ==
연산은
'참조변수의 참조 값'에 대한
비교 연산을 진행한다.
예를 들어서 아래 코드를
실행할 경우
== 연산의 결과로 true가
출력된다.
public static void main(String[] args){
AAA inst1 = new AAA();
AAA inst2 = inst1; // 두 참조변수는 동일 인스턴스 참조
System.out.println(inst1 == inst2); // 같은 인스턴스를 참조하므로 true 출력
}
반면 다음의 코드를 실행할
경우 == 연산의 결과로
false가 출력된다.
public static void main(String[] args){
AAA inst1 = new AAA();
AAA inst2 = new AAA();
System.out.println(inst1 == inst2); // 다른 인스턴스를 참조하므로 false 출력
}
따라서 예제의 실행 결과는,
다음 코드에서 str1과 str2가
참조하는 인스턴스는 같은
인스턴스이고,
String str1 = "Simple String";
String str2 = "Simple String";
다음과 같이 생성한 두
인스턴스는 서로 다른
인스턴스임을 알 수 있다.
String str3 = new String("Simple String");
String str4 = new String("Simple String");
그렇다면 이러한 차이를
보이는 이유는 무엇인가?
가장 핵심이 되는 이유는
다음과 같다.
String 인스턴스는 Immutable 인스턴스이다.
사전적 정의에 따르면, 'immutable'은
'변경할 수 없는'이라는 뜻을 지닌다.
그리고 String 인스턴스에서
변경할 수 없는 것은
인스턴스가 갖는 문자열
내용이다.
예를 들어서 다음과 같이
String 인스턴스를 생성하면,
String str = "AtoZ";
이 때 생성된 인스턴스 내부에
문자열 "AtoZ"를 지니게 되고,
이 내용은 인스턴스가 소멸될
때까지 바꿀 수 없다.
때문에 다음과 같이 인스턴스를
생성하면,
String str1 = "AtoZ";
String str2 = "AtoZ"
'문자열 내용이 같기 때문에'
다음과 같이 하나의 인스턴스를
생성해서
이를 공유하는 방식으로 코드를
처리한다.
이로 인해 생성되는 인스턴스의 수는 줄고 성능은 향상된다.
String str1 = "Simple String";
String str2 = str1;
그렇다면 이렇게 하나의 인스턴스를
공유해도 문제가 되지 않을까?
대부분의 경우에는 문제가
되지 않는다.
문제가 되는 상황이라면 new를 이용하여 String 인스턴스를 생성하면 된다.
이유는 String 인스턴스는
그 안에 저장된 데이터를
수정할 수 없는,
참조만 가능한 인스턴스이기
때문이다.
만약에 이 부분이 이해가
되지 않는다면 TV 시청을
비유로 이해를 도울 수 있다.
세 사람이 있고 모두 동일한
채널을 시청하면서
채널을 결코 변경하지 않는다면
인스턴스를 참조만 하고 있는 상황이라면
한 대의 TV로 모두가 시청을
할 수 있다.
그러나 동일한 채널을 시청하다가
각 사람이 원할 때 TV 채널을
변경해야 한다면
인스턴스 안에 저장된 데이터를 변경해야 한다면
각 사람에게 한 대씩 TV가
있어야 한다.
참고 - 문자열의 내용 비교
String 인스턴스가 지니는
문자열의 내용을 비교하기
위해서는
equals라는 메소드를 사용해야
하는데
이 방법에 대해서는 이후에
별도로 설명을 진행한다.
그러니 여기서는 간단히
코드만 보이겠다.
public static void main(String[] args){
String str1 = new String("AtoZ");
String str2 = new String("AtoZ");
// 문자열의 내용이 같으면 equals 메소드는 true 반환
if (str1.equals(str2))
System.out.println("두 문자열의 내용이 같습니다.");
else
System.out.println("두 문자열의 내용이 다릅니다.");
}
String 인스턴스를 이용한 switch문의 구성
자바 7부터 String 인스턴스를
이용한 switch문의 구성이
가능해졌다.
즉 다음과 같이 switch문을
구성할 수 있다.
public static void main(String[] args){
String str = "two";
switch (str){
case "one":
System.out.println("one");
break;
case "two":
System.out.println("two");
break;
default:
System.out.println("default");
break;
}
}
위와 같은 switch문의 구성이
일반적이지는 않으나,
각 case 영역을 설명하는
문장을 구성할 수 있다는
측면에서
긍정적인 부분도 존재한다.
참고 및 출처
|