String클래스, 문자열 비교, 빈 문자열
String클래스
- String클래스 = 데이터(Char[]) + 메서드(문자열 관련)
String클래스는 문자열을 다루는데 사용되는 클래스다.
String클래스는 데이터와 메서드로 이루어져 있다.
데이터는, 문자배열을 가지고있고,
그리고 이 문자배열을 다루는데에 필요한 메서드를 가지고 있다.
예를들어, C언어 같은 경우에는 String클래스가 없다. 왜냐하면 객체지향 언어가 아니라서 문자배열에 문자를 저장하는 것은 똑같은데,
이 문자배열을 다루는데 사용되는 메서드들이 따로있다. 즉, 하나의 클르스에 묶여있는 것이 아니라 따로 존재한다.
그런데 자바에서 클래스는 데이터와 관련된 메서드를 같이 묶어놓은 것이다.
String클래스의 실제코드인데,
구현부안에 private으로 문자 배열을 가지고 있다. 그리고 뒤에 생략된 부분에느 이 문자배열을 다루는데 필요한 메서드들이 잔뜩 들어있다.
- 내용을 변경할 수 없는 불변(immutable) 클래스
String의 특징중에 하나는, 내용을 변경할 수 없는 불변 클래스라는 뜻이다.
immutable클래스인데, mut가 change라는 뜻인데, im붙어서 not이 붙은 즉, 내용을 변경할 수 없는 불변클래스이다.
이렇게 String a 와 String b가 있을 때,
a + b를 하면 문자열 "ab"가 만들어지고, a의 내요잉 바뀌는 것처럼 보이지만,
실제로 문장이 실행되는 과정을 보면,
먼저 String a와 String b가 만들어지고,
a+b연산에 의해서 "a"와 "b"가 합쳐져서 "ab"가 만들어지는데,
그러면 이 결과 "ab"가 String a 에 들어가는게 아니라,
완전히 새로운 문자열이 만들어 지는 것이다.
왜냐하면 String은 불변 클래스이기 떄문이다.
그래서, a에는 새로 만들어진 문자열의 주소가 a에 저장되는 것이다.
그래서 System.out.println으로 a를 찍어보면, a가 가리키는 "ab"가 찍히는 것이다.
- 덧셈 연산자(+)를 이용한 문자열 결합은 성능이 떨어짐
그래서 덧셈 연산자(+)를 이용한 문자열 결합은 성능이 떨어진다.
왜냐하면, 문자열 내용을 변경할 수 없어서 계속 새로운 객체가 만들어 지기 때문이다.
그러면 문자열 변경을 자주해야 하는 경우에는 어떡할까?
그럴때는, StringBuffer라는 클래스를 이용한다.
- 문자열의 결합이나 변경이 잦다면, 내용 변경이 가능한 StringBuffer클래스를 사용
String클래스처럼 문자열을 저장하고 다루기 위한 클래스지만, String과 달리, StringBuffer클래스는 내용을 변경할 수 있다.
간단한 문자열 결합, 한두번은 괜찮지만, 반복문 안에서 지속적으로 문자열을 결합한다던가 하는 경우에는 반드시 StringBuffer를 사용하길 권장한다.
문자열의 비교
- String str = "abc;와 String str = new String("abc")의 비교
문자열을 만들 때, 문자열 리터럴을 이용해서 만드는 방법과,
String은 클래스이므로 new를 이용해서 문자열을 만들 수도 있다.
이 두가지 방법에 대해서 비교해보자.
str1과 str2는 문자열 리터럴을 저장했고,
str3과 str4는 new연산자를 이용해서 문자열 객체를 만들었다.
그림으로 표현해보면,
str1과 str2는 주소값이 동일한 문자열 "abc"가리키고,
str3과 str4는 각각의 문자열을 가리키고 있다.
즉, 문자열 리터럴로 문자를 만들면, 하나의 문자열을 여러 참조변수가 공유한다.
그런데
new연산자를 사용하면 항상 새로운 객체가 만들어진다.
문자열은 내용 변경이 불가능하다. 그래서 어차피 내용을 바꿀 수 없기 때문에,
여러 참조변수가 하나의 문자열을 공유해도 별 문제가 없다.
굳이 new연산자를 이용해서 같은 내용의 문자열을 여러번 만들 필요가 없다.
특별한 경우를 제외하고는, 굳이 이렇게 만들 필요가 없다.
그래서 str1 == str2로 비교해보면, 참조변수의 값이 같기 때문에 true이다.
str3 == str4 를 비교해보면, 서로 다른 객체이므로 참조변수아 각각 다른 주소값이 저장되어 있으므로 false이다.
이처럼 생성 방식에 따라 같은 문자열의 비교인데도, false가 나올 수 있기 때문에,
문자열의 비교에는 equals()를 사용해야 한다.
equals를 사용하면, 내용비교이므로 항상 true이다.
그런데, 등가비교연산자는, 주소비교라서 어떨때는 true고, 어떨때는 false이다.
그래서, 문자열 비교할 때는, 항상 equals()를 이용해서 비교 해야한다.
문자열 리터럴로 만들면 하나만 만들어지고, 문자열 리터럴을 공유한다고 했는데, 그이유를 알아보자.
문자열 리터럴
- 문자열 리터럴은 프로그램 실행시 자동으로 생성된다. (constant pool에 저장)
문자열 리터럴은 프로그램 실행시에 자동으로 생성된다.
예를 들어 위와 같은 코드를 작성하면,
우리가 만든 프로그램에 있는 모든 문자열은 자동으로 생성된다.
원래 String이 클래스여서 객체 생성을 해야하지만,
문자열 리털러로 적은 것은, 프로그램 실행시 자동으로 생성된다.
만들어져서 constatnt pool(상수 저장소)이라는 곳에 저장이 된다.
프로그램에 있는 모든 상수는 자동으로 constant pool에 저장된다.
- 같은 내용의 문자열 리터럴은 하나만 만들어진다.
그래서 자동으로 만들어진 문자열 리터럴도 String객체다.
자동으로 만들어진 String객체를 s1, s2, s3 참조변수가 공유한다.
즉, 각 참조변수들이 하나의 스트링 객체를 가리키게 된다.
String객체는 불변이기 때문이다. 내용을 바꿀 수 없으니까, 여러 참조변수가 하나의 String객체를 공유해도 아무런 문제가 없다.
빈 문자열("", empty string)
- 내용이 없는 문자열. 크기가 0인 char형 배열을 저장하는 문자열
아무런 내용도 없는 문자열을 빈 문자열이라고 한다.
보통 String타입의 참조변수는, 빈 문자열로 초기화를 한다.
빈 문자열은 크기가 0인 배열이다.
- 길이가 0인 배열을 생성하는 것은 어느 타입이나 가능
자바에서는 크기가 0인배열을 허용한다.
char뿐만 아니라, 어느 타입이라도 길이가 0인 배열을 생성하는 것이 가능하다.
- 문자(char)와 문자열(String)의 초기화
문자와 문자열의 초기화는 null로 하거나, 유니코드의 첫번째 문자 즉, 기본값으로 초기화 하기보다는,
우측 예시처럼 String은 ""빈 문자열로 초기화를 하고,
char은 ' '공백으로 초기화 한다.
그리고 이 두 코드 형식중에,
좌측코드가 더 좋은 코드이다.
우측코드는, 내용이 같아도 무조건 객체를 새로 만들기 때문에, 3개를 만들어서 메모리가 낭비된다.
좌측코드가 하나의 빈 문자열을 str1, str2, str3 참조변수가 공유하기 때문이다.
코드를 좌측 처럼 작성하길 권장한다.
'JAVA' 카테고리의 다른 글
StringJoiner, 문자열과 기본형 변환 (0) | 2022.04.15 |
---|---|
String 생성자 (0) | 2022.04.15 |
hashCode(), toString() (0) | 2022.04.14 |
Object클래스와 equals() (0) | 2022.04.13 |
연결된 예외 (0) | 2022.04.12 |
댓글
이 글 공유하기
다른 글
-
StringJoiner, 문자열과 기본형 변환
StringJoiner, 문자열과 기본형 변환
2022.04.15 -
String 생성자
String 생성자
2022.04.15 -
hashCode(), toString()
hashCode(), toString()
2022.04.14 -
Object클래스와 equals()
Object클래스와 equals()
2022.04.13