Java에서 문자열은 매우 중요한 데이터 형식으로 사용되며, 문자열을 효율적으로 처리하기 위해 String, StringBuffer, StringBuilder 세 가지 클래스가 제공된다. 개발자는 각 클래스를 사용 목적에 맞게 선택함으로써 프로그램의 성능과 안정성을 극대화할 수 있다.
String 클래스는 불변성으로 안정성을 보장하며, 문자열 수정이 거의 없는 경우에 적합하다.
StringBuffer 클래스는 멀티스레드 환경에서 안전하게 문자열을 동적으로 수정할 때 사용한다.
StringBuilder 클래스는 단일 스레드 환경에서 빠르게 문자열을 처리할 때 사용한다.
전체 코드
public class Main {
public static void main(String[] args) {
// String 예시
String str1 = "Hello";
String str2 = "World";
String resultStr = str1 + " " + str2;
System.out.println("String 예시: " + resultStr);
// StringBuffer 예시
StringBuffer buffer = new StringBuffer("Hello");
buffer.append(" World");
String resultBuffer = buffer.toString();
System.out.println("StringBuffer 예시: " + resultBuffer);
// StringBuilder 예시
StringBuilder builder = new StringBuilder("Hello");
builder.append(" World");
String resultBuilder = builder.toString();
System.out.println("StringBuilder 예시: " + resultBuilder);
}
}
실행 결과
String 예시: Hello World
StringBuffer 예시: Hello World
StringBuilder 예시: Hello World
각 예시에서 생성된 문자열은 모두 "Hello World"이지만, 각 클래스의 내부적인 처리 방식이 다르기 때문에 코드에서 사용된 방식들이 다르다. 어떤 차이가 있는지 알아보도록 하자.
💡String 클래스
String str = "Hello";
str += " World";
String 클래스는 불변(Immutable)한 특성을 가지고 있다. 즉, 한 번 생성된 String 객체는 그 값을 변경할 수 없다.
문자열 연산 시마다 새로운 String 객체가 생성되어 오버헤드가 발생한다.
멀티스레드 환경에서는 동기화에 대한 걱정이 없으며, 안전하게 사용할 수 있다.
문자열 연산이 적고, 주로 조회가 많은 환경에서 사용된다.
String 클래스 메서드
리턴 타입 | 메서드 | 사용 예시 | 예제 | 결과 |
char | charAt(int index) | 특정 위치의 문자 리턴 | char ch = str.charAt(6); | 'W' |
boolean | equals(Object anObject) | 두 문자열 비교 | boolean isEqual = str.equals("Hello World"); | true |
byte[] | getBytes() | byte[]로 리턴 | byte[] bytes = str.getBytes(); | byte 배열 |
byte[] | getBytes(Charset charset) | 주어진 문자셋으로 인코딩한 byte[]로 리턴 | byte[] bytes = str.getBytes(StandardCharsets.UTF_8); | byte 배열 |
int | indexOf(String str) | 문자열 내에서 주어진 문자열의 위치 리턴 | int index = str.indexOf("World"); | 6 |
int | length() | 총 문자의 수 리턴 | int length = str.length(); | 11 |
String | replace(CharSequence target, CharSequence replacement) | target 부분을 replacement로 대치한 새로운 문자열 리턴 | String replacedStr = str.replace("World", "Java"); | "Hello Java" |
String | substring(int beginIndex) | beginIndex 위치에서 끝까지 잘라낸 새로운 문자열 리턴 | String subStr1 = str.substring(6); | "World" |
String | substring(int beginIndex, int endIndex) | beginIndex 위치에서 endIndex 전까지 잘라낸 새로운 문자열 리턴 | String subStr2 = str.substring(0, 5); | "Hello" |
String | toLowerCase() | 알파벳 소문자로 변환한 새로운 문자열 리턴 | String lowerCaseStr = str.toLowerCase(); | "hello world" |
String | toUpperCase() | 알파벳 대문자로 변환한 새로운 문자열 리턴 | String upperCaseStr = str.toUpperCase(); | "HELLO WORLD" |
String | trim() | 앞뒤 공백을 제거한 새로운 문자열 리턴 | String trimmedStr = " Hello ".trim(); | "Hello" |
String | valueOf(int i) / valueOf(double d) | 기본 타입 값을 문자열로 리턴 | String intStr = String.valueOf(10); | "10" |
String doubleStr = String.valueOf(3.14); | "3.14" |
String 클래스 메서드 전체 코드
public class Main {
public static void main(String[] args) {
// 문자열 "Hello"를 변수에 할당합니다.
String str = "Hello";
// charAt() 메서드를 사용하여 특정 위치의 문자를 가져와 출력합니다.
char ch = str.charAt(1);
System.out.println("charAt(1): " + ch);
// equals() 메서드를 사용하여 두 문자열을 비교합니다.
boolean isEqual = str.equals("Hello");
System.out.println("equals(\"Hello\"): " + isEqual);
// indexOf() 메서드를 사용하여 문자열 내에서 특정 문자열의 위치를 찾습니다.
int index = str.indexOf("e");
System.out.println("indexOf(\"e\"): " + index);
// length() 메서드를 사용하여 문자열의 길이를 출력합니다.
int length = str.length();
System.out.println("length(): " + length);
// replace() 메서드를 사용하여 문자열의 일부를 다른 문자열로 대체합니다.
String replacedStr = str.replace("Hello", "Hi");
System.out.println("replace(\"Hello\", \"Hi\"): " + replacedStr);
// substring() 메서드를 사용하여 부분 문자열을 추출합니다.
String subStr = str.substring(1, 3);
System.out.println("substring(1, 3): " + subStr);
// toLowerCase() 메서드를 사용하여 문자열을 소문자로 변환합니다.
String lowerCaseStr = str.toLowerCase();
System.out.println("toLowerCase(): " + lowerCaseStr);
// toUpperCase() 메서드를 사용하여 문자열을 대문자로 변환합니다.
String upperCaseStr = str.toUpperCase();
System.out.println("toUpperCase(): " + upperCaseStr);
// trim() 메서드를 사용하여 문자열의 앞뒤 공백을 제거합니다.
String trimmedStr = " Hello ".trim();
System.out.println("trim(): \"" + trimmedStr + "\"");
// valueOf() 메서드를 사용하여 기본 타입 값을 문자열로 변환합니다.
String intStr = String.valueOf(10);
System.out.println("valueOf(10): " + intStr);
// double 타입 값을 문자열로 변환합니다.
String doubleStr = String.valueOf(3.14);
System.out.println("valueOf(3.14): " + doubleStr);
}
}
실행 결과
charAt(1): e
equals("Hello"): true
indexOf("e"): 1
length(): 5
replace("Hello", "Hi"): Hi
substring(1, 3): el
toLowerCase(): hello
toUpperCase(): HELLO
trim(): "Hello"
valueOf(10): 10
valueOf(3.14): 3.14
💡StringBuffer 클래스
StringBuffer buffer = new StringBuffer("Hello");
buffer.append(" World");
StringBuffer 클래스는 가변(Mutable)한 특성을 가지고 있다. 따라서 문자열을 동적으로 수정할 수 있다.
문자열 연산 시 새로운 객체를 생성하지 않고, 기존의 StringBuffer 객체를 수정한다.
멀티스레드 환경에서는 동기화가 가능하므로 스레드 안전(Thread-Safe)하게 사용할 수 있다.
StringBuffer 클래스 메서드
메서드 | 설명 | 예제 | 결과 |
append() | 매개변수로 입력된 값을 문자열로 변환하여 StringBuffer에 추가 | StringBuffer sb = new StringBuffer("Hello"); sb.append(" world"); | sb = "Hello world" |
capacity() | StringBuffer 인스턴스의 버퍼 크기를 반환 | StringBuffer sb = new StringBuffer(10); sb.append("ABCD"); int bufferSize = sb.capacity(); | bufferSize = 100, sb = "ABCD" |
charAt(int index) | 지정된 위치(index)에 있는 문자를 반환 | StringBuffer sb = new StringBuffer("Hello"); char c = sb.charAt(1); | c = 'e' |
delete(int start, int end) | 시작 위치부터 끝 위치 사이에 있는 문자를 제거한다. 단, 끝 위치의 문자는 제외 | StringBuffer sb = new StringBuffer("Hello"); sb.delete(1,4); | sb = "Heo" |
deleteCharAt(int index) | 지정된 위치(index)의 문자를 제거 | StringBuffer sb = new StringBuffer("Hello"); sb.deleteCharAt(1); | sb = "Hllo" |
insert(int pos, 매개변수) | 지정된 위치(pos) 앞에 두 번째 매개변수로 받은 값을 문자열로 변환하여 추가 | StringBuffer sb = new StringBuffer("0123456"); sb.insert(4,'ABC'); | sb = "0123ABC456" |
replace(int start, int end, String str) | 지정된 범위의 문자들을 주어진 문자열로 변경. End 위치는 범위에 포함하지 않음 | StringBuffer sb = new StringBuffer("0123456"); sb.replace(3, 6, "AB"); | sb = "012AB6" |
reverse() | StringBuffer 인스턴스에 저장된 문자열의 순서를 거꾸로 나열 | StringBuffer sb = new StringBuffer("0123456"); sb.reverse(); | sb = "6543210" |
setCharAt(int index, char ch) | 지정된 위치의 문자를 주어진 문자로 변경 | StringBuffer sb = new StringBuffer("0123456"); sb.setCharAt(5, 'A'); | sb = "01234A6" |
setLength(int newLength) | 문자열의 길이를 지정된 길이로 변경. 빈 공간은 null ('\u0000')로 변환 | StringBuffer sb = new StringBuffer("0123456"); sb.setLength(5); | sb = "01234" |
toString() | StringBuffer 인스턴스의 문자열을 String으로 변환 | StringBuffer sb = new StringBuffer("0123456"); String str = sb.toString(); | str = "0123456" |
substring(int start) | 지정된 시작 위치부터 끝까지의 문자열을 반환 | StringBuffer sb = new StringBuffer("0123456"); String str = sb.substring(3); | str = "3456" |
substring(int start, int end) | 시작 위치부터 끝 위치 전까지의 문자열을 반환 | StringBuffer sb = new StringBuffer("0123456"); String str2 = sb.substring(3, 5); | str2 = "34 |
StringBuffer 클래스 메서드 전체 코드
public class Main {
public static void main(String[] args) {
// StringBuffer 객체 생성
StringBuffer buffer = new StringBuffer("Hello");
// append() 메서드를 사용하여 문자열을 추가합니다.
buffer.append(" World");
System.out.println("append(): " + buffer);
// capacity() 메서드를 사용하여 버퍼의 크기를 확인합니다.
int bufferSize = buffer.capacity();
System.out.println("capacity(): " + bufferSize);
// charAt() 메서드를 사용하여 특정 위치의 문자를 가져옵니다.
char ch = buffer.charAt(1);
System.out.println("charAt(1): " + ch);
// delete() 메서드를 사용하여 문자열 일부를 삭제합니다.
buffer.delete(1, 4);
System.out.println("delete(1, 4): " + buffer);
// deleteCharAt() 메서드를 사용하여 특정 위치의 문자를 삭제합니다.
buffer.deleteCharAt(1);
System.out.println("deleteCharAt(1): " + buffer);
// insert() 메서드를 사용하여 문자열을 특정 위치에 삽입합니다.
buffer.insert(1, "ABC");
System.out.println("insert(1, \"ABC\"): " + buffer);
// replace() 메서드를 사용하여 문자열의 일부를 대체합니다.
buffer.replace(3, 6, "DEF");
System.out.println("replace(3, 6, \"DEF\"): " + buffer);
// reverse() 메서드를 사용하여 문자열을 뒤집습니다.
buffer.reverse();
System.out.println("reverse(): " + buffer);
// setCharAt() 메서드를 사용하여 특정 위치의 문자를 변경합니다.
buffer.setCharAt(5, 'X');
System.out.println("setCharAt(5, 'X'): " + buffer);
// setLength() 메서드를 사용하여 문자열의 길이를 조정합니다.
buffer.setLength(5);
System.out.println("setLength(5): " + buffer);
// toString() 메서드를 사용하여 StringBuffer를 String으로 변환합니다.
String result = buffer.toString();
System.out.println("toString(): " + result);
// substring() 메서드를 사용하여 부분 문자열을 추출합니다.
String subString = buffer.substring(3);
System.out.println("substring(3): " + subString);
}
}
실행 결과
append(): Hello World
capacity(): 21
charAt(1): e
delete(1, 4): H World
deleteCharAt(1): HWorld
insert(1, "ABC"): HABCWorld
replace(3, 6, "DEF"): HABCFWorld
reverse(): dlroWFCBAH
setCharAt(5, 'X'): dlroWXCBAH
setLength(5): dlroW
toString(): dlroW
substring(3): oW
💡StringBuilder 클래스
StringBuilder builder = new StringBuilder("Hello");
builder.append(" World");
StringBuilder 클래스도 가변(Mutable)한 특성을 가지고 있다. StringBuffer와 유사하지만 스레드 안전하지 않다. 따라서 단일 스레드 환경에서 사용할 때 더 빠르게 동작한다.
StringBuilder 클래스 메서드
메서드 | 설명 | 예제 | 결과 |
append(String str) | 문자열 추가 | sb.append("bbb") | (이전 문자열) + "bbb" |
insert(int offset, String str) | offset 위치에 str 추가 | sb.insert(2, "ccc") | (이전 문자열의 2번 위치) + "ccc" |
replace(int start, int end, String str) | start부터 end-1까지의 문자열을 str로 대체 | sb.replace(3, 6, "ye") | (이전 문자열에서 3부터 5까지의 문자열) + "ye" + (이전 문자열의 6부터 끝까지) |
substring(int start, int end) | 인덱싱. start부터 end-1까지의 문자열 추출 | sb.substring(3, 7) | (이전 문자열에서 3부터 6까지의 문자열) |
deleteCharAt(int index) | 인덱스에 위치한 문자 하나 삭제 | sb.deleteCharAt(3) | (이전 문자열에서 3번 위치의 문자를 제거한 결과) |
delete(int start, int end) | start부터 end-1 까지의 문자 삭제 | sb.delete(3, sb.length()) | (이전 문자열에서 3부터 끝까지의 문자를 제거한 결과) |
toString() | StringBuilder 객체를 String으로 변환 | sb.toString() | StringBuilder 객체의 문자열 표현 |
reverse() | 문자열을 뒤집음 | sb.reverse() | (이전 문자열을 뒤집은 결과) |
setCharAt(int index, char c) | index 위치의 문자를 c로 변경 | sb.setCharAt(2, 'x') | (이전 문자열에서 2번 위치의 문자를 'x'로 변경한 결과) |
setLength(int len) | 문자열 길이 조정 | sb.setLength(5) | (이전 문자열의 길이를 5로 조정한 결과) |
trimToSize() | 문자열의 저장된 char[] 배열의 사이즈 조정 | sb.trimToSize() | 문자열 뒷부분의 공백을 모두 제거한 결과 |
StringBuilder 클래스 메서드 전체 코드
public class Main {
public static void main(String[] args) {
// StringBuilder 객체 생성
StringBuilder builder = new StringBuilder("Hello");
// append() 메서드를 사용하여 문자열을 추가합니다.
builder.append(" World");
System.out.println("append(): " + builder);
// insert() 메서드를 사용하여 문자열을 특정 위치에 삽입합니다.
builder.insert(2, "ABC");
System.out.println("insert(2, \"ABC\"): " + builder);
// replace() 메서드를 사용하여 문자열의 일부를 대체합니다.
builder.replace(3, 6, "DEF");
System.out.println("replace(3, 6, \"DEF\"): " + builder);
// substring() 메서드를 사용하여 부분 문자열을 추출합니다.
String subString = builder.substring(3, 7);
System.out.println("substring(3, 7): " + subString);
// deleteCharAt() 메서드를 사용하여 특정 위치의 문자를 삭제합니다.
builder.deleteCharAt(3);
System.out.println("deleteCharAt(3): " + builder);
// delete() 메서드를 사용하여 문자열의 일부를 삭제합니다.
builder.delete(3, builder.length());
System.out.println("delete(3, builder.length()): " + builder);
// reverse() 메서드를 사용하여 문자열을 뒤집습니다.
builder.reverse();
System.out.println("reverse(): " + builder);
// setCharAt() 메서드를 사용하여 특정 위치의 문자를 변경합니다.
builder.setCharAt(2, 'X');
System.out.println("setCharAt(2, 'X'): " + builder);
// setLength() 메서드를 사용하여 문자열의 길이를 조정합니다.
builder.setLength(5);
System.out.println("setLength(5): " + builder);
// toString() 메서드를 사용하여 StringBuilder를 String으로 변환합니다.
String result = builder.toString();
System.out.println("toString(): " + result);
}
}
실행 결과
append(): Hello World
insert(2, "ABC"): HeABCllo World
replace(3, 6, "DEF"): HeDEFlo World
substring(3, 7): DEFl
deleteCharAt(3): HeFlo World
delete(3, builder.length()): HeF
reverse(): Feh
setCharAt(2, 'X'): FeX
setLength(5): FeX
toString(): FeX
참고 자료
String, StringBuffer, StringBuilder, Drashti Koladiya, 2021.10.21.
[Java] 자바 문자열을 다루는 String 클래스 메소드 총정리, 혼공족장, 2023.03.20.
[Java/자바] StringBuffer 클래스 사용법, Hyun / Log, 2022.10.24.