LALA's blog
[우테코 강의] 문자와 문자열 ( String , StringBuilder , StringBuffer ) 본문
문자와 문자열
- 문자열(String) 은 자바 프로그램이 실행되는 동안 가장 많이 생성되는 객체이다.
- 문자열은 객체이지만 각각의 문자의 나열로 구성된다.
char capitalA = 'A'; // 문자
Strinng a = "abc"; // 문자열 == 문자의 배열
String b = new String("abc"); // 이와 같이 구현하지 마라.
String 은 가장 많이 사용되는 객체이기 때문에 가장 최적화가 잘 되어있다.
🤔. 문자열들은 어디서 관리되는 될까?
- Constant Pool 에 저장이 돼서 계속 재사용할 수 있게 된다.
- 아래의 두 문자열은 같은 객체를 바라보고 있다.
String string1 = "string";
String string2 = "string";
String 도 객체인데 왜 new 키워드를 사용해서 생성하지 않을까?
- new 키워드를 사용하면 무조건 새로운 객체를 반환되어야 한다.
- 재사용하며 사용하기 때문에 new 키워드를 붙혀서 사용하지 않는다. (사용하지 않도록 한다.)
위의 두 객체는 같은 객체로 봐야한다. == 동일하다고 봐야한다.
동등성 vs 동일성 ????
동등성
assertThat(string1.equals(string2)).isTrue();
assertThat(sstring1).isEqualTo(string2);
동일성
assertThat(string1 == string2).isTrue();
assertThat(string1).isSameAs(string2);
🤔. 그럼 string1 과 string2 는 equals() 가 아닌 == 로 비교해야 하는 것이 아닌가?
- 항상 동일하다는 보장을 해주진 못한다.
String string1 = "string";
String string2 = new String("string");
- 이처럼 어떤 곳에서는 new 를 통해 새로운 객체로 생성됐을 수도 있다.
- JDK 버전에 따라서 String Pool 의 관리 방식이 다를 수 있기 때문이다.
- 8 버전 이상부터는 GC 대상이 되기 때문에 다른 객체가 될 수도 있다. (아직 몰라도 됨)
String Pool 이 존재하고, 이를 통해 자바가 알아서 최적화시켜주고 있다 !!
String k = new String("k");
String a = "a";
String b = "b";
String c = "c";
여기서 객체는 몇개 생성될까 ?
- 1 개 ^___^
byte code 보는 법 ⬇️
프로젝트 > build > classes > java > 해당 파일 경로
Navigate 메뉴 > Search EveryWhere > show byte 검색
- byte code 를 살펴보면 String k 는 NEW 로 생성되었다.
- 나머지 a, b, c 는 생성되지 않았다.
- 컴파일 시점에 고정되어 있는 값들은 최적화를 하기 때문에 런타임에 생성되는 것이 아닌 경우 대부분 컴파일 타임에 만들어 지니다고 보면 된다.
이 경우엔?
String a = "a";
String b = "b";
String c = "c";
System.out.println(a + b + c);
자바 11 에서는 StringConcatFactory.makeConcatWithConstants 를 통해 최적화를 해서 abc 를 합친 문자열로 만들어버린다.
🤔. a + b + c 를 최적화를 해준 이유가 뭘까?
최적화 하지 않으면 + 할 때 마다 새로운 객체를 만들기 때문이다.
a + b = "ab" 가 만들어지고
ab + c = "abc" 가 만들어지게 된다.
최적화 하는 다른 방법
- final 키워드를 붙혀준다.
final String a = "a";
final String b = "b";
final String c = "c";
System.out.println(a + b + c);
final 키워드를 붙혀주니 "abc" 객체가 생성된 것을 볼 수 있다.
컴파일 타임에 변하지 않는 값이라는 것을 이미 알기 때문에 최적화하기 굉장히 좋은 경우이므로 최적화가 가능하다.
String 을 1000 번 + 해준다면 어떻게 될까?
String text = "";
for (int i = 0; i < 1000; i++) {
text += i;
}
- + 연산을 할 때마다 객체를 생성할 것 같다.
- 자바 8 에서는 StringBuilder 로 최적화해주는 것을 볼 수 있다.
오 JVM 완전 똑똑한데?
우리의 예상
StringBuilder text = new StringBuilder();
for (int i = 0; i < 1000; i++) {
text.append(i);
}
이렇게 해주겠지?
현실..
String text = "";
for (int i = 0; i < 1000; i++) {
text = new StringBuilder(text).append(i).toString();
}
매번 StringBuilder 가 생성되는 것이다. 생각보다 멍청하군?
따라서 가변적인 문자열인 경우 우리가 직접 StringBuilder 를 적용하는 것이 좋다.
StringBuilder vs StringBuffer
- StringBuffer 는 thread-safe 하다는 특징이 있다.
- StringBuffer 는 자바 1 버전에 생겼다
- StringBuilder 는 1.5 버전에 생겼다. (최신 기술)
🤔. thread-safe 한 경우에 StringBuffer 를 쓰면 될까?
- String 을 멀티 쓰레딩 환경에서 쓸 일이 있을까? 생각해보고 써라.
- 메소드들에 synchronized 덕지덕지 붙어있어서 성능만 떨어짐. ㅎ
- 아무도 사용하지 않아서,, 생긴게 StringBuilder 이다. (만든사람도 후회중 ㅋ)
immutable
- immutable(불변)이란 객체를 생성한 후 상태를 변경할 수 없는 것을 의미한다.
- String 객체는 문자열의 상태 값을 변경할 수 없기 때문에 immutable 객체라 한다.
🤔. 아니 그래서.. String vs StringBuilder vs StringBuffer vs StringConcatFactory 뭐가 제일 좋나 ?
- StringBuilder 가 제일 빠르기 때문에 좋긴 하다.
- StringBuilder 는 byte[] 로 저장하고 있기 때문에 배열의 size 도 정할 수 있고, 중간 중간에 size 도 늘려주는 기능도 있다.
- StringConcatFactory 는 내부 로직이 복잡하고, 추가적인 객체들도 많은 단점이 있다.
'개발 > 우아한테크코스' 카테고리의 다른 글
[레벨1] 어떤 값을 상수로 관리해야 할까? (3) | 2022.03.04 |
---|---|
[우테코 강의] 자바 List, Generic (0) | 2022.02.25 |
DTO 란? 장점은? (0) | 2022.02.17 |
[우아한테크코스 4기] 프리코스 3주차 회고 (0) | 2021.12.14 |
[우아한테크코스 4기] 프리코스 2주차 회고 (0) | 2021.12.07 |