부트캠프에서 처음으로 java수업을 받고 있기에 기록하는 게 좋다고 생각했고, 수업이 있는 날이면 매일 글을 쓰려고 합니다. 쵀대한 몰랐거나 필요하다고 생각되는 내용 위주로 기록할 예정입니다. (제가 게을러서 이러한 시도를 성공한 적이 없기에 이번 부트캠프 목표 중 1가지입니다. 할 수 있도록 화이팅!!)
String Pool(문자열 상수 풀)은 JVM의 Heap 메모리 내에 존재하는 특별한 영역으로, 동일한 문자열 리터럴을 한 번만 저장하여 메모리를 절약하는 기법이다.
1️⃣ 메모리 절약: 동일한 문자열을 여러 개 생성해도 String Pool에서 공유되므로 메모리를 아낄 수 있음.
2️⃣ 성능 향상: String Pool을 활용하면 객체 생성 비용이 줄어들고, 비교 연산(==)이 더 빠르게 수행됨.
String str1 = "hello";
String str2 = "hello";
String str3 = new String("hello");
String str4 = new String("hello").intern();
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // false
System.out.println(str1 == str4); // true
코드 | String Pool 적용? | 설명 |
---|---|---|
String s1 = "java"; | ✅ 적용 | 리터럴 사용 시 String Pool에 저장 |
String s2 = "java"; | ✅ 적용 | 기존 "java" 참조를 재사용 |
String s3 = new String("java"); | ❌ 미적용 | Heap에 새로운 객체 생성 |
String s4 = new String("java").intern(); | ✅ 적용 | intern() 으로 String Pool에 등록 |
String
클래스는 불변(immutable) 클래스로 , 한 번 생성된 문자열 객체는 변경할 수 없고 새로운 객체를 생성함
StringBuilder
: 가변(mutable) 클래스로. 즉, 한 번 생성된 객체 내에서 문자열을 수정할 수 있으며, 새로운 객체가 생성되지 않음.
항목 | String | StringBuilder |
---|---|---|
가변성 | 불변(immutable) | 가변(mutable) |
메모리 사용 | 문자열을 수정할 때마다 새로운 객체 생성 | 기존 객체 내에서 문자열을 수정 |
성능 | 문자열을 자주 수정하면 비효율적 (새로운 객체가 계속 생성됨) | 문자열을 자주 수정하는 데 효율적 |
스레드 안전성 | 스레드 안전함 | 스레드 안전하지 않음 |
사용 용도 | 문자열이 변경되지 않거나, 변경이 적은 경우 | 문자열을 자주 변경하거나 추가하는 경우 |
제네릭은 데이터의 형식에 의존하지 않고 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 프로그래밍 방식이다.
public class GenericTest<T> { // 1. T라는 타입 파라미터를 사용하는 제네릭 클래스
private T value; // 2. T 타입의 value 필드
// 3. T 타입의 값을 설정하는 메서드
public void setValue(T value) {
this.value = value;
}
// 4. T 타입의 값을 반환하는 메서드
public T getValue() {
return this.value;
}
}
// 사용 예제
public class Main {
public static void main(String[] args) {
// String 타입을 사용하는 GenericTest 클래스
GenericTest<String> stringTest = new GenericTest<>(); // 괄호 수정
GenericTest<Integer> integerTest = new GenericTest<>(); // 괄호 수정
// 값 설정
stringTest.setValue("Hello, Generics!");
integerTest.setValue(100);
// 값 가져오기
String value1 = stringTest.getValue();
Integer value2 = integerTest.getValue();
System.out.println(value1); // "Hello, Generics!" 출력
System.out.println(value2); // 100 출력
}
}
제네릭에서 와일드카드 ?를 사용하면, 타입에 구체적인 제한을 두지 않고, 범용적으로 사용할 수 있다.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void printList(List<?> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
public static void main(String[] args) {
List<String> strList = new ArrayList<>();
strList.add("Hello");
strList.add("World");
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
printList(strList);
printList(intList);
}
}
int[] arr = new int[5];
와 같이 크기를 지정하면 배열의 크기는 5로 고정되고 크기를 늘리거나 줄이는 것은 불가하다.즉 배열(Array)는 고정 크기로 빠른 데이터 접근과 효율성을 제공하지만, 크기 변경이나 삽입, 삭제에 제한이 있다.
List<Integer> list = new ArrayList<>();
처럼 사용하면, 리스트의 크기를 자유롭게 추가하거나 삭제할 수 있다.즉 리스트 (List)는 동적 크기로 데이터를 삽입하고 삭제하는 데 유용하며, 제네릭을 지원해 타입 안전성을 제공한다. ArrayList와 LinkedList와 같은 다양한 구현체를 제공하므로 상황에 맞는 자료구조를 선택 가능하다.