9osari.log
← 목록으로

[JAVA] String 클래스

2025년 5월 7일 · #java#김영한-java-중급

자바에서 문자열

문자 하나: char

char c = 'A';

자바에서 문자를 다루는 가장 기본적인 타입.

char[] arr = {'h', 'e', 'l', 'l', 'o'};
System.out.println(arr); // hello

문자열: String

String str1 = "hello";             //리터럴 방식
String str2 = new String("hello"); // 객체 생성 방식

String 클래스는 참조형

String a = "hello";
String b = " java";
System.out.println(a.concat(b)); // hello java
System.out.println(a + b);       // hello java
//+ 연산자는 자바가 내부적으로 StringBuilder 를 사용해 최적화함

문자열 비교 == vs equals()

String s1 = new String("hello");
String s2 = new String("hello");

System.out.println(s1 == s2);       // false: 참조값 비교
System.out.println(s1.equals(s2));  // true: 문자열 내용 비교

String s3 = "hello";
String s4 = "hello";

System.out.println(s3 == s4);       // true: 문자열 풀 덕분에 같은 참조
System.out.println(s3.equals(s4));  // true

String 클래스 - 불변 객체

불변 객체란?

String str = "hello";
str.concat(" java");
System.out.println("str = " + str); // 출력: hello

concat() 은 새로운 문자열을 반환하지만 str 변수에 할당하지 않았기 때문에 원본은 변하지 않는다.

String이 불변하게 설계된 이유

String a = "hello";
String b = "hello";
// 만약 b가 내부 값을 바꾸면? → a 도 영향을 받게 됨 (위험!)

이런 문제를 방지하기 위해 String은 불변으로 설계되었다.

String 주요 메서드

문자열 정보 확인

String str = "Hello, Java!";
str.length();      // 12
str.isEmpty();     // false
str.isBlank();     // false (Java 11 이상)
str.charAt(7);     // 'J'

문자열 비교

str1.equals(str2);               // 값 비교
str1.equalsIgnoreCase(str2);    // 대소문자 무시
str1.compareTo(str3);           // 사전순 비교
str1.startsWith("Hello");       // true
str1.endsWith("Java!");         // true

문자열 검색

str.contains("Java");           // true
str.indexOf("Java");            // 첫 등장 위치
str.lastIndexOf("Java");        // 마지막 등장 위치

이 외에도 substring, replace, split, join, format, matches 등

문자열 조작 및 변환

부분 문자열 추출: substring()

String str = "Hello, Java!";
str.substring(7);        // "Java!"
str.substring(7, 12);    // "Java!"

문자열 연결: concat()

str.concat("!!!");       // "Hello, Java!!!!"

문자열 치환: replace(), replaceFirst(), replaceAll()

str.replace("Java", "World");         // 모든 Java → World
str.replaceFirst("Java", "World");    // 첫 번째 Java → World

대소문자 변환: toLowerCase(), toUpperCase()

str.toLowerCase(); // 소문자
str.toUpperCase(); // 대문자

공백 제거: trim(), strip(), stripLeading(), stripTrailing()

str.trim();          // 양쪽 공백 제거
str.strip();         // 양쪽 유니코드 공백 제거 (Java 11+)
str.stripLeading();  // 앞 공백 제거
str.stripTrailing(); // 뒤 공백 제거

문자열 분할 및 결합

분할: split()

String str = "Apple,Banana,Orange";
String[] arr = str.split(",");

결합: String.join()

String.join("-", "A", "B", "C"); // "A-B-C"
String.join("-", arr);           // "Apple-Banana-Orange"

기타 유틸리티

문자열 변환: valueOf()

String.valueOf(100);      // "100"
String.valueOf(true);     // "true"
String.valueOf(obj);      // obj.toString() 값

참고: "" + x 로도 문자열 변환 가능

문자 배열 변환: toCharArray()

char[] chars = str.toCharArray();

문자열 포맷: String.format(), System.out.printf()

String.format("숫자: %d, 문자열: %s", 10, "hello");
// 출력: 숫자: 10, 문자열: hello
포맷 코드설명
%d정수 (int)
%s문자열 (String)
%bboolean 값
%f실수 (float)

정규식 매칭: matches()

str.matches("Hello, (Java!|World!)"); // true

StringBuilder

불변인 String의 단점

String str = "A" + "B" + "C" + "D"; // 실제론 여러 객체 생성됨

StringBuilder(가변 문자열) 등장

StringBuilder sb = new StringBuilder();
sb.append("A").append("B").append("C");
System.out.println(sb.toString()); // ABC

StringBuilder는 쓰레드 안전하지 않음. 멀티쓰레드 환경에서는 StringBuffer 사용

StringBuilder 주요 메서드

메서드설명
append(str)문자열 추가
insert(idx, str)특정 위치에 삽입
delete(start, end)특정 범위 삭제
reverse()문자열 뒤집기
toString()최종 문자열 반환 (String)
StringBuilder sb = new StringBuilder("ABCD");
sb.insert(4, "Java");          // ABCDJava
sb.delete(4, 8);               // ABCD
sb.reverse();                  // DCBA
String result = sb.toString(); // DCBA

성능 비교: 반복문에서 문자열 더하기

String 사용 시 (비효율적)

String result = "";
for (int i = 0; i < 100000; i++) {
    result += "Hello ";
}

StringBuilder 사용 시

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
    sb.append("Hello ");
}
String result = sb.toString();

자바의 문자열 최적화


언제 StringBuilder를 직접 써야 할까?

상황설명
반복문에서 문자열 결합루프마다 문자열 생성 방지
조건문 등 동적 조합if, switch 등에서 조합이 자주 발생할 때
긴 문자열예: HTML 생성, 로그 조립 등
문자열 일부 변경중간 삽입, 삭제, 교체

StringBuilder vs StringBuffer

클래스쓰레드 안전성속도
StringBuilder비동기 → 빠름빠름
StringBuffer동기화 → 안전느림

멀티쓰레드 환경에선 StringBuffer 사용. 단일 스레드에선 StringBuilder가 성능 우위



StringBuilder와 메서드 체인(Chain)

StringBuilder 는 메서드 체이닝 기법을 제공한다

메서드 체이닝이란?

기본 구조

public class ValueAdder {
    private int value;

    public ValueAdder add(int addValue) {
        value += addValue;
        return this; // 자신의 참조값 반환
    }

    public int getValue() {
        return value;
    }
}

일반 호출 vs 체이닝 호출

일반 방식

ValueAdder adder = new ValueAdder();
adder.add(1);
adder.add(2);
adder.add(3);
System.out.println(adder.getValue()); // 6

체이닝 방식

ValueAdder adder = new ValueAdder();
int result = adder.add(1).add(2).add(3).getValue();
System.out.println(result); // 6

변수 선언 없이 바로 연결 가능 → 코드가 간결해짐


StringBuilder와 메서드 체이닝

자바의 StringBuilder도 체이닝을 지원하는 대표적인 클래스

String result = new StringBuilder()
    .append("A")
    .append("B")
    .append("C")
    .append("D")
    .insert(4, "Java")
    .delete(4, 8)
    .reverse()
    .toString();

System.out.println(result); // DCBA

append(), insert(), delete() 등 거의 모든 메서드가 this를 반환함

→ 한 줄로 복잡한 문자열 처리 가능


체이닝이 가능한 이유

코드가 간결해지고 가독성이 좋아지지만, 너무 길거나 조건문이 섞이면 오히려 가독성이 저하된다. 메서드 체이닝은 클래스 작성자는 조금 번거롭지만, 사용자는 훨씬 편리해진다.



출처: 김영한의 실전 자바 - 중급 1편

···
← PREV [JAVA] 불변 객체 NEXT → [JAVA] 래퍼, Class 클래스