1. String 클래스
자바에서 String 클래스는 문자열 데이터를 표현하기 위한 클래스로, 문자들의 집합을 객체 형태로 다룰 수 있도록 해줍니다. String은 불변(immutable) 특성을 가지며, 한 번 생성된 문자열은 수정할 수 없고, 변경이 필요한 경우 새로운 문자열 객체가 생성됩니다. 문자열 리터럴은 자동으로 String 객체로 취급되며, 다양한 문자열 조작 메서드(length(), substring(), charAt(), equals(), toUpperCase() 등)를 제공하여 문자열을 효율적으로 처리할 수 있습니다. 또한 String은 자바에서 매우 중요한 클래스이기 때문에 기본 타입처럼 사용할 수 있는 특수한 참조형 객체이며, + 연산자를 통한 문자열 연결, ==과 equals()의 차이 등은 중요한 개념으로 자주 등장합니다.
1. 문자열 불변(Immutable)
- String 객체는 한 번 생성되면 수정이 불가능
- 문자열을 변경하면 새로운 String 객체가 생성됨
String str = "Hello";
str = str + " World"; // 기존 "Hello"는 버려지고 새로운 "Hello World" 객체가 생성됨
2. 문자열은 리터럴 풀에서 공유
- 같은 문자열 리터럴은 JVM이 하나만 생성해서 공유
- == 연산자는 주소(참조값) 비교이고, equals()는 내용 비교
String a = "Java";
String b = "Java";
System.out.println(a == b); // true (같은 주소)
System.out.println(a.equals(b)); // true (같은 내용)
3. 문자열 생성
String s1 = "hello"; // 리터럴 방식 (문자열 풀에 저장)
String s2 = new String("hello"); // 명시적 생성 (heap에 새 객체)
리터럴 방식
String s1 = "hello";
- "hello" 리터럴은 상수 풀에 존재하고,
- new String("hello")는 힙 영역에 별로로 새 객체를 생성합니다.
- 즉, 같은 "hello"라은 문자열이 상수 풀과 힙에 각각 존재하게 됩니다.
따라서 s1 == s2 → false (주소 다름), s1.equals(s2) → true (내용 같음)
4. 상수 풀(Constant Pool)
메모리를 절약하고 성능을 향상시키기 위해 만들어진 특수한 저장 공간입니다. 문자열뿐만 아니라 다른 종류의 상수와 참조 정보도 저장됩니다.
문자열 리터럴 (String Literals): 문자열 리터럴은 자동으로 상수 풀에 저장되며, 동일한 문자열은 공유됨
String s1 = "hello";
String s2 = "hello"; // 기존 "hello" 재사용됨 (상수 풀 공유)
기본형 상수 (정수, 실수, 문자, boolean 등): final로 선언된 기본형 상수값들은 컴파일 시 상수 풀에 저장됩니다.
final int A = 100;
final double PI = 3.14;
클래스, 메서드, 필드 이름 등 (바이트코드 수준에서): 컴파일된 .class 파일 안에는 java/lang/System, out, println, "Hello" 같은 문자열이나 심볼이 상수 풀 테이블(Constant Pool Table)에 저장되어 있음
System.out.println("Hello");
위 코드가 컴파일되면 .class 파일 안의 상수 풀에는 다음 정보들이 저장됩니다.
- "Hello" -> 문자열 리터럴
- java/lang/System -> 클래스 이름
- out -> 필드 이름
- java/io/PrintStream -> 필드 타입
- print-> 메서드 이름
- (Ljava/lang/String;)V -> 메서드 시그니처
중요한 건 이 정보들이 저장된다고 해서 객체가 만들어진 건 아니라는 점입니다. JVM이 클래스를 로딩하고 실행할 때 이 정보들을 사용해서 객체를 만들거나 메서드를 호출하는 것입니다.
2. 주요 메서드
1. 문자열 길이, 문자 추출
String s = "Hello";
System.out.println("길이: " + s.length()); // 5
System.out.println("첫 글자: " + s.charAt(0)); // H
2. 문자열 비교
String a = "Java";
String b = new String("Java");
System.out.println(a == b); // false (주소 다름)
System.out.println(a.equals(b)); // true (내용 같음)
3. 문자열 자르기와 대소문자 변경
String s = "HelloWorld";
System.out.println(s.substring(0, 5)); // Hello
System.out.println(s.toUpperCase()); // HELLOWORLD
System.out.println(s.toLowerCase()); // helloworld
4. 문자열 포함 여부, 치환
String msg = "오늘은 자바를 공부하는 날입니다.";
System.out.println(msg.contains("자바")); // true
System.out.println(msg.replace("자바", "파이썬")); // 오늘은 파이썬을 공부하는 날입니다.
5. 문자열 나누기
String csv = "사과,바나나,딸기";
String[] fruits = csv.split(",");
for (String fruit : fruits) {
System.out.println(fruit);
}
6. 문자열 합치기
String str = "hi";
str.concat(" there"); // 원본 문자열에는 변화 없음
System.out.println(str); // "hi"
str = str.concat(" there");
System.out.println(str); // "hi there"