안녕하세요
오늘은 String 객체에 대한 이야기를 해보겠습니다.
문자열 생성
문자열은 자바에서 객체로 취급한다는거 알고 계셨나요?
int,double,char는 원시 타입으로 해서 객체가 아닙니다.
그러므로 자체적으로 구현된 메소드들 또한 없죠. 위 타입을 객체 처럼 사용하기 위해서는
이미 만들어진 Wrapper 클래스를 사용하면 됩니다.
한번 String 객체를 생성해 보겠습니다.
// 1
String str1 = new String("Hello World");
String str2 = new String("Hello World");
// 2
String str3 = "Hello World";
String str4 = "Hello world";
위 사진은 보기 코드에 첫번째 new 로 객체를 생성했을 때의 메모리 구조입니다.
String 안에 들어가 있는 값은 같지만, 각각의 객체를 생성했기 때문에
메모리 공간이 총 2개가 만들어집니다.
그리고 위 객체를 비교해보면
str1==str2;
str1.equals(str2);
false
true
위 결과를 얻게 됩니다. 간단하게 설명을 하자면
== 연산자는 Stack 메모리의 주소를 비교합니다. 그러므로 원시 타입을 비교할때 알맞겠죠?
그러므로 두 객체는 각각의 다른 메모리 공간을 가지고 있음으로 false가 나옵니다
그러나 equals 메소드는 Heap 메모리에 저장된 실제 값을 비교합니다
Heap 메모리에 저장된 두 값은 'Hello World' 로 같은 값을 가지니 true가 나옵니다.
위 사진은 new로 객체를 생성하지 않았을 때 문자열 메모리 입니다.
stack 메모리에 2가지 주소가 생깁니다
그리고 오른쪽에 메모리 공간을 보면 Heap이 아닌 Literal Pool Memory 라는 공간에 저장되어 있습니다
자바에는 String 문자를 저장하는 공간이 따로 마련되어 있습니다
그 공간은 Literal Pool 이라고 부르고요
일반적인 String 변수를 선언하면 Heap 메모리에 값이 저장되지 않고,
Literal Pool 에 저장이 됩니다.
String str1 = "abc";
String str2 = "abc";
System.out.println(str1.equals(str2));
System.out.println(str1==str2);
위 값을 비교를 하면은
true
true
가 나옵니다. 왜그럴까요?
String 은 이미 만들어진 변수와 같은 값을 가진 변수가 있으면
객체를 새로 만들지 않고, 같은 주소를 가리키게 만든다
그게 가능한 이유는 Literal Pool 은 재활용이 가능한 성질이 있기 때문입니다
그래서 == ,equals()를 비교해도 true 가 나오는 것 입니다.
그럼 이번에는 위 new로 생성한 객체와 new가 없이 생성한 객체를 비교하면 같은 문자로 취급할까?
위 고민을 해결하기 위해서 테스트를 해본 결과 false 가 나왔습니다.
왜 그런걸까요?
이제 한번 알아보겠습니다.
public class Ex1 {
public static void main(String[] args) {
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1==str2);
System.out.println(str1.equals(str2));
}
}
false
true
위 코드를 실행시켜보면 위와 같은 결과가 나오게 됩니다.
왜 그런지를 이해하고 위해선 JVM 메모리에 대한 이해가 필요 합니다.
위에서 설명을 한 내용하고 비슷합니다.
자바에서 new 는 객체를 생성할 때 사용합니다.
new 를 사용하면, Heap Memory에 객체를 생성을 하는 것이다
위 코드를 보면 한개는 new 를 썻고, 한개는 new 를 쓰지 않았다
다시 설명을 하자면
new를 사용하지 않고, 변수를 선언한 경우에는
Heap 메모리에 변수가 저장되지 않고
JVM 에 String 변수를 저장할 LiteralPool Memory 에 따로 저장이 됩니다.
보통 객체 같은 경우에는
Stack 메모리에 객체의 주소가 저장되어 있고
Heap 메모리에 객체의 값이 들어가 있습니다.
위 설명을 보고 차이를 보자면, 일반적으로
== 비교연산자를 통해서 비교를 하면,
== 비교 연산자는 Stack 메모리를 비교합니다.
그러므로 == 연산자를 통해서 비교를 하면은 주소가 다르니
false
가 나옵니다
그러나 equals 메소드를 통해서 비교를 해보면
equals 메소드는 Heap 메모리의 값을 직접 비교를 합니다.
그러면 결과는
true
가 나오게 됩니다.
문자열을 비교할때는 Stack 이 아닌 Heap 영역을 봐야하기 때문에
'==' 연산자는 사용하지 않는 것이 좋고, equals() 메소드를 사용해야합니다.
또 다른 방법으로 문자열을 비교하는 방법은
'compareTo()' 메소드를 이용하면 됩니다.
문자열을 사전순으로 비교하며, 두 문자열이 같으면 0을 반환하고,
비교 대상 문자열이 기준 문자열보다 작으면 음수를 크면 양수를 반환합니다.
위 방법은 문자열을 대소를 비교하는 것 입니다. 어떤 문자열이 더 크고 작은지
String str1 = "abc";
String str2 = "abc";
String str3 = "abcd";
System.out.println(str1.compareTo(str2));
System.out.println(str1.compareTo(str3));
0
-1
위 결과를 반환하게 됩니다.
이상입니다. 틀린 내용이 있을시 지적해주세요 감사합니다.