1️⃣ String
String의 특징
- 불변(Immutable): 한 번 생성된 문자열은 변경 불가능.
- 새로운 문자열을 생성해야 변경이 가능하여, 성능적으로 비효율적일 수 있음.
- String Pool 사용: 동일한 문자열을 재사용하여 메모리 절약 가능.
String 선언 및 초기화
// 리터럴 방식 (String Pool 사용, 같은 값이면 재사용)
String str1 = "Hello";
// new 키워드 사용 (Heap 메모리에 새로운 객체 생성)
String str2 = new String("Hello");
💡 리터럴 방식과 new 키워드 방식의 차이
- 리터럴 방식("Hello")은 String Pool에 저장되어 동일한 문자열이 있으면 재사용됩니다.
- new String("Hello")는 Heap 메모리에 새로운 객체를 생성합니다.
String 주요 메서드
String str = "Hello, Java!";
메서드 | 설명 | 예제 |
length() | 문자열 길이 반환 | str.length(); // 12 |
charAt(int index) | 특정 인덱스의 문자 반환 | str.charAt(1); // 'e' |
indexOf(String s) | 문자열 위치 반환 | str.indexOf("Java"); // 7 |
contains(String s) | 특정 문자열 포함 여부 | str.contains("Java"); // true |
substring(int start, int end) | 부분 문자열 반환 | str.substring(7, 11); // "Java" |
replace(String old, String new) | 특정 문자열 반환 | str.replace("Java", "World"); // "Hello, World!" |
toUpperCase() | 대문자로 변환 | str.toUpperCase(); // "HELLO, JAVA!" |
toLowerCase() | 소문자로 변환 | str.toLowerCase(); // "hello, java!" |
trim() | 앞뒤 공백 제거 | " Hello ".trim(); // "Hello" |
split(String regex) | 특정 구분자로 문자열 분리 | str.split(","); // ["Hello", " Java!"] |
2️⃣ StringBuffer
StringBuffer의 특징
- 가변(Mutable): String과 달리 동일 객체 내에서 문자열 변경 가능.
- 멀티스레드 환경에서 안전(Thread-Safe): 내부적으로 synchronized가 적용되어 있음.
- 성능은 StringBuilder보다 느리지만, 멀티스레드 환경에서는 안정적.
StringBuffer 선언 및 초기화
// 기본 생성자 (빈 문자열)
StringBuffer sb1 = new StringBuffer();
// 초기 문자열을 지정하여 생성
StringBuffer sb2 = new StringBuffer("Hello");
// 용량(capacity) 지정하여 생성
StringBuffer sb3 = new StringBuffer(50);
StringBuffer 주요 메서드
StringBuffer sb = new StringBuffer("Hello");
메서드 | 설명 | 예제 |
append(String s) | 문자열 추가 | sb.append(" Java!"); // "Hello Java!" |
insert(int offset, String s) | 특정 위치에 문자열 삽입 | sb.insert(6, "World "); // "Hello World Java!" |
replace(int start, int end, String s) | 특정 범위 문자열 변경 | sb.replace(6, 11, "Awesome"); // "Hello Awesome Java!" |
delete(int start, int end) | 특정 범위 문자열 삭제 | sb.delete(6, 13); // "Hello Java!" |
reverse() | 문자열 뒤집기 | sb.reverse(); // "!avaJ olleH" |
length() | 문자열 길이 반환 | sb.length(); // 12 |
charAt(int index) | 특정 인덱스의 문자 반환 | sb.charAt(1); // 'e' |
setCharAt(int index, char c) | 특정 인덱스 문자 변경 | sb.setCharAt(0, 'h'); // "hello, Java!" |
3️⃣ StringBuilder
StringBuilder의 특징
- StringBuffer와 거의 동일하지만, 동기화(synchronized)가 없음.
- 단일 스레드 환경에서 가장 빠른 성능 제공.
- 멀티스레드 환경에서는 안전하지 않음.
StringBuilder 선언 및 초기화
// 기본 생성자 (빈 문자열)
StringBuilder sb1 = new StringBuilder();
// 초기 문자열을 지정하여 생성
StringBuilder sb2 = new StringBuilder("Hello");
// 용량(capacity) 지정하여 생성
StringBuilder sb3 = new StringBuilder(50);
StringBuilder 주요 메서드
StringBuilder sb = new StringBuilder("Hello");
메서드 | 설명 | 예제 |
append(String s) | 문자열 추가 | sb.append(" Java!"); // "Hello Java!" |
insert(int offset, String s) | 특정 위치에 문자열 삽입 | sb.insert(6, "World "); // "Hello World Java!" |
replace(int start, int end, String s) | 특정 범위 문자열 변경 | sb.replace(6, 11, "Awesome"); // "Hello Awesome Java!" |
delete(int start, int end) | 특정 범위 문자열 삭제 | sb.delete(6, 13); // "Hello Java!" |
reverse() | 문자열 뒤집기 | sb.reverse(); // "!avaJ olleH" |
length() | 문자열 길이 반환 | sb.length(); // 12 |
charAt(int index) | 특정 인덱스의 문자 반환 | sb.charAt(1); // 'e' |
setCharAt(int index, char c) | 특정 인덱스 문자 변경 | sb.setCharAt(0, 'h'); // "hello, Java!" |
4️⃣ String vs StringBuffer vs StringBuilder
비교표
구분 | String | StringBuffer | StringBuilder |
메모리 구조 | String Pool (리터럴 방식) 또는 Heap (new 사용) | Heap 메모리 | Heap 메모리 |
변경 가능 여부 | 불변(Immutable) | 가변(Mutable) | 가변(Mutable) |
멀티스레드 지원 | ❌ (동기화 없음) | ✅ (동기화 O, Thread-Safe) | ❌ (동기화 없음) |
성능 | 가장 느림 (새로운 객체 생성) | 느림 (동기화 O) | 가장 빠름 (동기화 X) |
주요 용도 | 문자열 변경이 거의 없을 때 | 멀티스레드 환경에서 문자열을 자주 변경할 때 | 단일 스레드 환경에서 문자열을 자주 변경할 때 |
선택 기준
- String → 문자열 변경이 거의 없는 경우 (불변성이 보장되므로 메모리 절약 가능)
- StringBuffer → 멀티스레드 환경에서 문자열을 자주 변경할 경우 (동기화 지원)
- StringBuilder → 단일 스레드 환경에서 문자열을 자주 변경할 경우 (속도 빠름)
성능 비교
public class StringPerformanceTest {
public static void main(String[] args) {
long startTime, endTime;
// String 테스트
String str = "";
startTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
str += "a"; // 새로운 객체 생성 (비효율적)
}
endTime = System.nanoTime();
System.out.println("String 실행 시간: " + (endTime - startTime) + "ns");
// StringBuffer 테스트
StringBuffer sbf = new StringBuffer();
startTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
sbf.append("a");
}
endTime = System.nanoTime();
System.out.println("StringBuffer 실행 시간: " + (endTime - startTime) + "ns");
// StringBuilder 테스트
StringBuilder sbd = new StringBuilder();
startTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
sbd.append("a");
}
endTime = System.nanoTime();
System.out.println("StringBuilder 실행 시간: " + (endTime - startTime) + "ns");
}
}
- String이 가장 느림
- StringBuffer가 String보다 빠름
- StringBuilder가 가장 빠름
5️⃣ +) 문자형 데이터 char
Java에서 char 데이터 타입은 단일 문자를 저장하는 기본형(primitive) 데이터 타입이다.
char 특징
- 크기 : 2바이트 (16비트)
- 문자 인코딩 : UTF-16 (유니코드 지원)
- 값의 범위 : \\u0000 (0) ~ \\uffff (65535)
- 기본값 : \\u0000 (널 문자, '\\0')
- 연산 가능 여부 : 숫자로 변환하여 연산 가능 (ASCII/유니코드 활용)
📌 Java의 char는 C나 C++의 1바이트 문자(char)와 다르게 2바이트(16비트) 크기를 가지며, 유니코드(UTF-16)를 지원하여 다양한 언어의 문자를 표현할 수 있다.
char 선언 및 초기화
// 문자 리터럴로 초기화
char ch1 = 'A';
// 유니코드 값으로 초기화 (예: 'A'는 \\u0041)
char ch2 = '\\u0041';
// ASCII 코드 정수값으로 초기화 (예: 'A'는 65)
char ch3 = 65;
// 공백 문자 (스페이스)
char ch4 = ' ';
// 널 문자 (기본값)
char ch5 = '\\0';
🔹 유니코드 사용 (\\uXXXX)
- Java의 char는 유니코드 기반이므로, 유니코드 값으로 직접 초기화할 수 있다.
- 예: '한' → \\uD55C, 'A' → \\u0041
🔹 정수값(ASCII 코드)로 초기화 가능
- char는 내부적으로 정수(유니코드 값) 로 저장되므로, 정수값을 할당하면 해당 코드에 해당하는 문자가 저장된다.
- 예: char ch = 65; → 'A' 저장 (ASCII 코드 65)
char 주요 특징과 유의점
1. char는 정수형과 연산 가능
char는 내부적으로 숫자로 저장되므로 정수 연산이 가능하다.
char ch = 'A';
System.out.println(ch + 1); // 66 (ASCII 코드 값)
System.out.println((char)(ch + 1)); // 'B'
📌 'A' + 1은 66이지만, (char)로 변환하면 문자 'B'가 된다.
2. char는 문자열(String)과 다르다
char는 단일 문자를 저장하는 기본형 데이터 타입이고,String은 문자의 집합(문자열) 을 저장하는 참조형 데이터 타입이다.
char ch = 'A'; // 단일 문자
String str = "A"; // 문자열 (문자의 집합)
📌 문자 하나라도 ""(큰따옴표)를 사용하면 String 타입이 된다!
예: String str = "A"; // 올바름
예: char ch = "A"; // 오류! ('A' 사용해야 함)
3. char는 Character 클래스를 통해 객체처럼 사용 가능
Java는 기본형(char)을 객체로 다룰 수 있도록 Character 클래스를 제공한다.
char ch = 'a';
Character obj = Character.valueOf(ch);
Character 클래스의 주요 메서드
Character 클래스는 char 타입을 다루기 위한 유용한 메서드를 제공한다.
char ch = 'A';
메서드 | 설명 | 예제 |
Character.isLetter(char c) | 문자인지 확인 | Character.isLetter('A'); // true |
Character.isDigit(char c) | 숫자인지 확인 | Character.isDigit('5'); // true |
Character.isWhitespace(char c) | 공백인지 확인 | Character.isWhitespace(' '); // true |
Character.isUpperCase(char c) | 대문자인지 확인 | Character.isUpperCase('A'); // true |
Character.isLowerCase(char c) | 소문자인지 확인 | Character.isLowerCase('a'); // true |
Character.toUpperCase(char c) | 대문자로 변환 | Character.toUpperCase('b'); // 'B' |
Character.toLowerCase(char c) | 소문자로 변환 | Character.toLowerCase('G'); // 'g' |
Character.getNumericValue(char c) | 숫자로 변환 (문자 0~9) | Character.getNumericValue('8'); // 8 |