일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 파이썬
- 딩코딩코
- 백엔드
- 인터럽트핸들러
- 빈 라인
- AWS
- CPU의 구성요소
- 개발자
- hELLO 스킨
- it세계의 괴물들
- 백준
- 그림자 문제
- LAMBDA
- Roy Fielding
- 2903
- 공부
- 자바
- CS지식
- 카카오톡API
- 알고리즘
- mac 코드 블럭
- BOJ
- 코딩테스트
- 비전공자
- HTTP
- Java
- 개발공부
- 백엔드 면접지식
- 문자열
- transiant
- Today
- Total
아직은 NULL NULL 합니다
String, StringBuffer, StringBuilder의 차이 본문
서론
먼저, 여태껏 반말만 쓰다가, 한번 존댓말로 바꿔볼까 합니다.
뭔가 공개적인 공간이다 보니 반말이 익숙하지가 않더라고요 하하
오늘도 하루가 지났네요. 시간이 참 생각보다 빨리 가서 1분 1초를 허투루 쓰면 안 될 것 같다는 생각이 드네요.
항상 생각은 하고 있었지만, 학원을 수료하고 명백한 취준생(원래도 백수였지만^>^) 이 되니 더 조급해지고 그러네요.
그렇지만 여유를 갖고 해야할 일을 꾸준히 하다 보면 어느샌가 원하는 목표에 도달해 있기를 바랍니다.
저뿐만 아니라, 원하는 목표를 이루기 위해 노력하고 계신 여러분들께서도 요!
그런 뜻으로,
오늘도 제 블로그에 와 주신 분들께 감사드립니다. 바로 오늘 글의 주제에 대해 공유해 보도록 할게요.
본론
바로 속시~원하게 결론부터 말해보겠습니다.
String, StringBuffer, StringBuilder 의 차이점
문자열 추가나 변경 등의 작업이 많을 경우에는 StringBuffer, StringBuilder 를
문자열 변경 작업이 거의 없고 짧은 문자열 연산만 있을 경우에는 그냥 String 을 사용하는 것이 더 빠릅니다.
그리고 멀티스레드를 사용할 경우에는 StringBuffer 를,
싱글스레드를 사용할 경우에는 StringBuilder 를 사용하는 것이 성능에 좋습니다.
해당 차이점에 대해서 이해를 하기 위해 하나하나 클래스들의 특징을 살펴보겠습니다.
String 클래스 란 ?
데이터(char[ ], 문자배열) + 메서드( 문자열 관련해서 다루기 위한 존재) 로 이루어진 클래스 입니다.
다시 말해, 여러 개의 문자를 담기 위한 문자배열을 갖고 있으며, 이 문자배열을 다루기 위해 필요한 메서드 들을 가지고 있습니다.
String 클래스의 특징
이 String 클래스의 특징은 다른 StringBuffer, StringBuilder 클래스 와 명확하게 다른 차이점으로
한번 문자열을 선언하여 값이 초기화되면, 그 값을 변경할 수 없는 불변(immutable)클래스 입니다.
그림으로 살펴보자면, 이런 형식이 됩니다.
String str 을 통해 "문자열" 이라는 값을 변수에 대입함으로써 해당 변수는 메모리영역 어딘가에 생긴 "문자열" 값의 주소를 참조하고 있습니다. 그러다 str 변수에 값을 다시 대입했더니, "문자열" 값이 변경되는 게 아니라 다른 메모리영역에 "문자열2" 값이 생기고 해당 값을 str 변수가 참조하는 것으로 변경된 것을 확인할 수 있습니다. 추가적으로 참조받지 않는 객체가 된 "문자열" 은 가비지컬렉터가 회수하게 됩니다.
코드로 설명하자면,
// 여기서 리터럴 이란, 상수를 의미합니다.
String str1 = "abc"; // 문자열 리터럴 "abc" 의 주소가 str1 에 저장됩니다.
String str2 = "abc"; // 문자열 리터럴 "abc" 의 주소가 str2 에 저장됩니다.
// str1 과 str2 는 같은 주소를 공유하여 가르키게 됩니다.
String str3 = new String("abc"); // 새로운 String 인스턴스를 생성
String str4 = new String("abc"); // 새로운 String 인스턴스를 생성
// 즉, str3 과 str4 는 서로 다른 주소를 가르키게 됩니다. -> 그러면 더 많은 메모리를 차지하게 됩니다.
// 주소를 비교하는 '==' 연산자에서는
if(str1 == str2) // true 가 나오고
if(str3 == str4) // false 가 나오는 것을 확인할 수 있습니다.
// 내용을 비교하는 equlas 함수에서는
if(str1.equals(str2)) // 여전히 true 가 나오고
if(str3.equals(str4)) // 주소가 아닌 내용을 비교하므로 true 가 나오게 됩니다.
즉, String 클래스는 문자열 결합을 할 때마다 기존의 변수로 대입했을 때 변수 안의 값이 바뀌는 것이 아니라 새로운 문자열이 만들어지는 것을 볼 수 있습니다.
그래서 String 클래스를 확인하면,
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {
private final byte[] value; // 해당 부분을 확인할 수 있습니다.
/*
원래 jdk 8 까지는 bytep[] 가 아닌 char[] 로 문자배열이었는데, jdk 9 부터는 기존 char[] 에서
bytep[] 를 사용하여 String Compacting 을 통한 성능 및 heap 공간 효율(2byte -> 1byte) 을
높이도록 수정되었다고 합니다.
*/
여러 개의 문자 배열을 담기 위한 문자배열이 존재하는 것을 확인할 수 있습니다.
String 클래스의 단점
덧셈 연산자(+) 같은 문자열 결합은 String 클래스에서는 계속 새로운 객체가 만들어지기 때문에 성능이 저하되는 문제점이 발생합니다.
이를 위해 문자열의 결합이나 변경이 잦을 경우 StringBuffer 나 StringBuilder 클래스를 사용하게 되는 것입니다.
StringBuffer 클래스 란 ?
String 처럼 문자형 배열(char[ ]) 을 내부적으로 가지고 있습니다.
하지만 jdk 9 부터 String 클래스에서 언급했듯이 byte[ ] 형식으로 바뀌게 되었습니다.
StringBuffer 의 특징
아까 String 은 불변클래스 여서 다른 클래스들과의 가장 큰 차이점이라고 했었죠?
그렇다면 StringBuffer 는 불변의 반대인 가변적인 클래스 입니다.
이 이유는 StringBuffer 는 저장할 문자열의 길이를 고려해서 적절한 크기로 자동 생성하는 특징이 있습니다.
즉, 문자열 연산 등으로 기존 객체의 공간이 부족하게 되는 경우 기존의 버퍼 크기를 늘리며 유연하게 동작함으로써
가변적이라고 하는 것입니다.
그림으로 보자면,
StringBuffer 가 새로운 객체를 생성하여 abc 를 대입합니다.
이 값은 StringBuffer 가 적절한 크기로 문자열 길이를 고려하여 자동 생성한 문자배열에 들어가게 됩니다.
그리고 String 클래스와는 다르게 + 연산 같은게 아닌, 객체이기 때문에 append 라는 메서드를 사용하여
해당 값에 "123"을 붙여 해당 객체의 값을 변경시킵니다.
그래도 여전히 sb 라는 객체는 이 객체의 값인 문자배열을 참조하고 있는 것을 확인할 수 있습니다.
코드를 한번 가볍게 보자면,
public StringBuffer(int length) {
value = new char[length];
shared = false;
}
public StringBuffer() {
this(16); //-- 버퍼의 크기를 지정하지 않으면
// 버퍼의 크기는 16이 됩니다.(16에 의미가 있는 것은 아니라고 하네요. )
}
public StringBuffer(String str) {
this(str.length() + 16); //-- 지정한 문자열의 길이에 16을 더해 더 크게 버퍼를 생성합니다.
append(str);
}
// 버퍼의 크기(용량) 확인하는 팁
// .capacity() 라는 함수로 확인할 수 있습니다.
또 다른 특징은 StringBuffer 클래스는 동기화되어 있어, 멀티스레드에 안전하다(thread-safe)고 말할 수 있습니다.
이에 대한 설명은 StringBuilder 클래스에서 하도록 하겠습니다.
StringBuilder 클래스 란 ?
StringBuilder 클래스는 StringBuffer 와 완전히 똑같은 기능을 합니다.
버퍼 크기가 16으로 지정돼서 늘어나는 것과 가변적인 클래스인 것과,
사용되는 메서드(ex. append(), delete()) 등 완전히 똑같지만, 여기서 딱 하나 다른 차이점이 존재합니다.
바로 StringBuilder 는 동기화 되어 있지 않다는 특징을 가지고 있습니다.
이를 thread-safe 하지 않다고도 얘기할 수 있는데, 아까 위에서도 언급한 thread-safe 에 대해 짚고 넘어가겠습니다.
thread-safe 란 ?
이에 대한 개념을 이해하기 전에 스레드에 대한 개념을 이해해야 하는데,
스레드에 대한 주제가 아니기 때문에 간단하게 설명해 보겠습니다.
스레드에는 싱글스레드와 멀티스레드가 존재합니다.
말 그대로, 싱글스레드는 한 번에 1개만 작업하는 것, 멀티스레드는 한번에 여러 개 작업하는 것을 의미합니다.
여기서 thread-safe 하다는 말은 멀티스레드에서 나오게 된 말로,
동시에 여러 작업을 할 수 있다는 것은 데이터를 공유한다는 의미입니다.
이는 하나의 스레드가 작업하던 영역을 다른 스레드가 침범할 수 있다는 뜻입니다.
그래서 이로부터 데이터를 보호하기 위한 공간을 임계영역(Critical Section)이라고 하며,
이러한 동작을 동기화(Synchronized)라고 합니다.
결국 동기화를 하면 스레드가 안전하다는 말로 thread-safe 하다 라고 말하는 것입니다.
하지만 멀티스레드 프로그램이 아닌 경우 동기화는 불필요해지면서 성능저하가 발생되기에,
StringBuffer 를 사용하지 않고 동기화 되지 않는 StringBuilder 클래스를 사용하게 되는 것입니다.
StringBuffer 와 StringBuilder 클래스의 equals( )
아까 위에서 언급했듯이 StringBuffer 와 StringBuilder 는 아주 유사합니다.
그래서 StringBuffer 에 초점을 맞춰 설명하더라도,
StringBuffer키워드를 StringBuilder 로 바꿔서 사용하면 됩니다.
StringBuffer 는 equals() 메서드가 오버라이딩 되어있지 않습니다.
아까 위에서(라는 말을 굉장히 많이 쓰는 것 같은데, 맞습니다 ㅎ..ㅎ) String 클래스가 equals() 메서드를 통해
주소가 다른 새로운 인스턴스끼리 내용을 비교했을 때 같다면 true 가 나오는 것을 확인했었는데요!
StringBuffer 도 다른 주소를 참조하지만 내용은
같은 객체끼리 equals() 를 통해 내용(값)을 비교하면 될 거라고 생각했지만 그렇지 않더라고요.
공부하다 보니, equlas() 메서드는 StringBuffer 에 오버라이딩이 되어있지 않아서
'==' (주소비교하는 연산자) 비교했을 때와 같은 값이 나오게 됩니다.
코드로 한번 확인해 볼게요.
StringBuffer sb = new StringBuffer("abc");
StringBuffer sb2 = new StringBuffer("abc");
System.out.println(sb == sb2) // false
System.out.println(sb.equals(sb2)) // false
// 그래서 String 으로 변환 후에 equals() 로 변환해줘야 합니다.
// String 으로 변환하는 메서드는 toString() 을 사용하면 가능합니다.
String s = sb.toString();
String sb = sb2.toString();
System.out.println(s.equals(s2)); // true
이렇게 StringBuffer 와 StringBuilder 까지 살펴보았는데요!
StringBuffer, StringBuilder 에서 버퍼의 크기를 초기에 설정해줘야 하는데 이러한 동작으로 인해
속도가 느려질 수 있다고도 합니다.
그래서 정말 짧은 문자열 연산을 할 때는 오히려 String 클래스가 더 속도가 빠를 수 있습니다!
해당 블로그와 강의는 제가 공부하고, 블로그 정리에 참고했던 글입니다.
인파님 진짜 대단하신 것 같아요.. 블로그도 너무 예쁘시고, 유익하고 이해 잘 되게 정리까지 잘해주셔서 많은 도움이 됐습니다.
☕ 자바 String / StringBuffer / StringBuilder 차이점 & 성능 비교
자바에서는 대표적으로 문자열을 다루는 자료형 클래스로 String, StringBuffer, StringBuilder 라는 3가지 자료형을 지원한다. 위 3가지 클래스 자료형은 모두 문자열을 다루는데 있어 공통적으로 사용되
inpa.tistory.com
남궁성 선생님 영상입니다. 유튜브 영상자체가 올라가서 텍스트에 링크 연결하였습니다!
항상 도움을 받고 있는 자료여서 무료공개에 너무 감사할 따름입니다.
마무리
네.. 누군가에게 정보를 공유하기 위해 글을 쓴다는 것은 참 쉬운 일이 아닌 것 같아요.
이미 공부했던 내용임에도 잘못된 내용을 전달하지 않기 위해 또 공부한 기분입니다 하핳
언젠가는 이렇게 공부했던 내용이 다 제 머릿속에 남아서 술술 글이 써져서 30분 내로 글 작성이 끝났으면 좋겠어요 ㅠㅠ
블로그에 글 쓰는 건 재밌지만, 다른 공부하기에도 바쁜데 말이죠!!
그냥 제가 얼른 똑똑해져야겠습니다.
오늘도 끝까지 글 읽어봐 주신 분들께 감사드립니다!! 그럼, 좋은 밤.. 좋은 날 되세요 :)

'Computer Science > Java' 카테고리의 다른 글
Array, LinkedList, ArrayList의 차이점 (2) | 2023.10.24 |
---|---|
Reflection(리플렉션) 에 대한 개념 및 단점, 그럼에도 쓰는 이유 (2) | 2023.10.10 |
SerialVersionUID는 무엇이고 이를 선언해야 하는 이유가 무엇일까요? (0) | 2023.09.22 |