-
[Java] String 클래스Programming/Java 2024. 2. 6. 19:28728x90
String
public final class String extends Object implements Serializable, Comparable<String>, CharSequence
String 클래스는 final로 선언되어 있다.
String 클래스는 자식 클래스를 양산할 수 없다.
모든 클래스의 부모 클래스인 Object클래스를 확장했다.
- Serializable 인터페이스 : 구현해야 하는 메소드가 하나도 없는 특이한 인터페이스 - Comparable 인터페이스 : compareTo()메소드 하나만 선언되어 있다. - CharSequence 인터페이스 : 문자열을 다루기 위한 클래스 - StringBuilder, StringBuffer 클래스도 CharSequence인터페이스를 구현해 놓았다.
불변한 객체
String은 immutable한 객체이다. 한 번 만들어지면 그 값을 변경할 수 없다.(불변)
String str = "Hello "; str += "World";
위의 코드로 보면 불변이 아닌 변하는 객체같다.
하지만 아니다. 불변한 객체이다.
String문자열을 더하면 새로운 String객체가 생성되고, 기존 객체는 버려진다.
하나의 String을 만들어 계속 더하기 작업을 하면 계속 쓰레기를 만들게 된다.
쓰레기는 GC의 대상이다.
이러한 String의 단점을 보완하기 위해 StringBuffer와 StringBuilder가 나왔다.
문자열을 더하더라도 새로운 객체를 생성하지 않는다. 이 클래스 타입은 append()라는 메소드로 더하기 작업을 한다.
StringBuffer, StringBuilder는 CharSequence인터페이스를 구현했다.
그래서 하나의 클래스를 사용하여 매개 변수로 받는 작업을 할 때는 String, StringBuilder타입 보다 CharSequence타입으로 받는 것이 좋다.
- StringBuffer
Thread safe하다.
클래스에 문자열 처리를 위한 인스턴스 변수가 선언되었고, 여러 쓰레드에서 이 변수를 동시에 접근하는 일이 있을 경우에는 반드시 StringBuffer를 사용해야만 한다.
-StringBuilder
Thread safe하지 않다.
하나의 메소드 내에서 문자열을 생성하여 더할 경우에는 StringBuilder를 사용해도 상관없다.
Thread safe
해당 객체를 사용할 때 다른 스레드에 의해 값이 변경되지 않는 것을 보장하는 상태
스트링 리터럴
String 클래스는 다른 클래스들과 다른 특성이 있다.
String str1 = new String("heap"); String str2 = "heap"; String str3 = "heap";
str1은 new를 이용해 문자열을 생성하면 heap영역의 새로운 주소로 할당된다.
str2는 문자열 리터럴로 생성하는 방식으로 heap영역안에 있는 String Constant Pool이라는 영역에 할당된다.
str1과 str2는 같은 값을 가지고 있지만 다른 주소 값을 가진다.
str2과 str3는 같은 값을 가지고 있어, 같은 주소 값을 참조하게 된다.
(문자열이 담기는 상수풀의 위치는 자바7부터 Heap영역으로 옮겨졌다)
== , equals()
String클래스도 == 비교가 아닌 equals() 메소드를 사용해서 비교를 해야만 한다.
==은 주소값을 비교하고, equals()메소드는 저장한 값을 비교한다.
equals()를 제대로 사용하려면 오버라이딩해야한다.
● Constant Pool
자바에서는 객체를 재사용하기 위해 Constant Pool이라는 것이 만들어졌다. heap영역에 있다.
String의 경우 동일한 값을 갖는 객체가 있으면, 이미 만든 객체를 재사용한다.
'new'를 통해 생성하면 객체를 새로 생성하기 때문에 값이 같더라도 재활용되지 않고 별도의 객체를 생성한다.생성자
생성자 설명 String() 비어있는 String객체를 생성.
String name = null; 로 선언하는 것이 더 낫다.String(byte[] bytes) 현재 사용중인 플랫폼의 캐릭터 셋을 사용하여 제공된 byte배열을 디코딩한 String객체를 생성 String(byte[] bytes, String charsetName) 지정된 캐릭터 셋을 사용하여 제공된 byte배열을 디코딩한 String객체를 생성 ... ... String문자열을 byte로 변환
리턴 타입 메소드 이름 및 매개 변수 설명 byte[ ] getBytes() 기본 캐릭터 셋의 바이트 배열을 생성 byte[ ] getBytes(Charset charset) 지정한 캐릭터 셋 객체 타입으로 바이트 배열 생성 byte[ ] getBytes(String charsetName) 지정한 이름의 캐릭터 셋을 갖는 바이트 배열을 생성 UCS
Unicode Character Set
한글을 처리하기 위해 자바에서 많이 사용하는 캐릭터 셋
- UTF-8 :8비트
- EUC-KR : 8비트, 한글을 사용하기 위해 4바이트 사용
- UTF-16 : 16비트, 한글을 사용하기 위해 6바이트 사용
UTF-16 : 요즘 대부분 많이 사용하는 캐릭터 셋
모든 객체를 처리할 때에는 반드시 NULL체크를 해야 합니다.
메소드
- 문자열 길이 확인
public int length()
- 문자열이 비어있는지 확인
public boolean isEmpty()
- 문자열이 같은지 비교
public boolean equals(Object anObject) public boolean equalsIgnoreCase(String anotherString) // 대소문자 무시 // 매개 변수로 넘겨준 String객체가 알파벳 순으로 앞에 있으면 양수, 뒤에 있으면 음수 public int compareTo(String anotherString) public int compareToIgnoreCase(String str) public boolean contentEquals(StringBuffer sb) //매개 변수로 넘어오는 값과 String객체와 같은지를 비교 public boolean contentEquals(CharSequence cs)
매개 변수로 넘어온 값과 String객체가 같은지를 비교하는 메소드
String클래스도 == 비교가 아닌 equals() 메소드를 사용해서 비교를 해야만 한다.
Constant Pool : 자바에서는 객체를 재사용하기 위해 Constant Pool이라는 것이 만들어져 있고, String의 경우 동일한 값을 갖는 객체가 있으면, 이미 만든 객체를 재사용한다. 'new'를 통해 생성하면 객체를 새로 생성하기 때문에 값이 같더라도 재활용되지 않고 별도의 객체를 생성 heap영역에 있다.
-특정 조건에 맞는 문자열이 있는지를 확인하는 메소드
public boolean startsWith(String prefix) //매개 변수로 넘겨준 값으로 시작하는지를 확인 public boolean startsWith(String prefix, int toffset) public boolean endsWith(String suffix) //매개 변수로 넘어온 값으로 해당 문자열이 끝나는지를 확인하는 메소드 public boolean contains(CharSequence s) //중간에 특정 값이 있는지 확인 //매개 변수로 넘어온 값이 “정규 표현식”으로 되어 있어야 한다. //`java.util.regex` 패키지의 `Pattern` 클래스 API public boolean matches(String regex) //문자열 중에서 특정 영역이 매개 변수로 넘어온 문자열과 동일한지를 확인 public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) public boolean regionMatches(int toffset, String other, int ooffset, int len) /* boolean ignoreCase : true(대소문자 구분 안함), false(대소문자 구분함) int toffset : 비교 대상 문자열의 확인 시작 위치, String other : 존재하는지를 확인할 문자열 의미, int ooffset : other객체의 확인 시작 위치를 지정, int len : 비교할 char의 개수 */
-String내에서 위치를 찾아내는 방법
//앞에서부터 찾는다 public int indexOf(int ch) public int indexOf(int ch, int fromIndex) public int indexOf(String str) public int indexOf(String str, int fromIndex) //뒤에서 부터 찾는다 -> 오른쪽에서부터 검사해서 찾은 결과 값은 가장 왼쪽에서부터의 위치 public int lastIndexOf(int ch) public int lastIndexOf(int ch, int fromIndex) public int lastIndexOf(String str) public int lastIndexOf(String str, int fromIndex)
- String의 값의 일부를 추출
public char charAt(int index) // 특정 위치의 char값을 리턴 public int codePointAt(int index) // 특정 위치의 유니코드 값 리턴 public int codePointBefore(int index) //특정 위치 앞에 있는 char의 유니코드 값 리턴 public int codePointCount(int beginIndex, int endIndex) //지정한 범위에 있는 유니코드 개수 public int offsetByCodePoints(int index, int codePointOffset) //지정된 index부터 offset이 설정된 인덱스 리턴 //문자열 인코딩과 관련된 문제를 해결하기 위해서 사용 //매개 변수로 넘어온 dst라는 char배열 내에 srcBegin에서 srcEnd에 있는 char를 저장 //이때, dst배열의 시작 위치는 dstBegin public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
- char배열의 값을 String으로 변환
public static String copyValueOf(char[] data) // char배열에 있는 값을 문자열로 변환 //char values[] = new char[]{'J','a','v','a'}; //String javaText = String.copyValueOf(values); //offset위치부터 count까지의 개수만큼만 문자열로 변환 public static String copyValueOf(char[] data, int offset, int count)
"static 메소드"이기 때문에 static하게 호출해야 한다.
- String값을 char배열로 변환
public char[] toCharArray()
- 문자열의 일부 값을 잘라내는 메소드
public String substring(int beginIndex) //beginIndex부터 끝까지 public String substring(int beginIndex, int endIndex) // beginIndex부터 endIndex까지 public CharSequence subSequence(int beginIndex, int endIndex) //beginIndex부터 endIndex까지 CharSequence타입으로 리턴
c++의 substr와 매개 변수가 다르다.
c++은 substr(3, 3) : 3번 index부터 3개
java의 subString(3, 6) : 3번 index부터 6번 index까지
- 문자열을 여러 개의 String배열로 나누는 메소드
public String[] split(String regex) // regex에 있는 정규 표현식에 맞추어 문자열을 잘라 public String[] split(String regex, int limit) // String배열의 크기는 limit보다 커서는 안된다.
특정 알파벳이나 기호 하나 -> 문자열 나누기 : split()
특정 String으로 -> 문자열 나누기 : StringTokenizer클래스 사용하는게 더 낫다.
-String값을 바꾸는 메소드
public String trim() // 문자열의 맨 앞과 맨 뒤에 있는 공백들을 제거한 문자열 객체 리턴
- 내용을 교체하는 메소드
public String replace(char oldChar, char newChar) //oldChar값을 newChar로 대치 //문자열에 있는 target과 같은 값을 replacement로 대치 public String replace(CharSequence target, CharSequence replacement) //해당 문자열의 내용 중 regex에 표현된 정규 표현식에 포함되는 모든 내용을 replacement로 대치 public String replaceAll(String regex, String replacement) //해당 문자열의 내용 중 regex에 표현된 정규 표현식에 포함되는 첫번째 내용을 replacement로 대치 public String replaceFirst(String regex, String replacement)
- 특정 형식에 맞춰 값을 치환하는 메소드
public static String format(String format, Object... args) public static String format(Locale l, String format, Object... args) // Locale l : 지역적으로 다른 표현 형식을 제공하기 위한 것 // Locale을 지정하지 않으면 기본적으로 자바 프로그램이 수행되는 OS의 지역 정보 기반을 따른다.
System.out.format()메소드와는 다른 것이다.
- 대소문자 바꾸는 메소드
public String toLowerCase() //모든 문자열의 내용을 소문자로 변경 public String toLowerCase(Locale locale) // 지정한 지역 정보에 맞추어 모든 문자열의 내용을 소문자로 변경 public String toUpperCase() public String toUpperCase(Locale locale)
- 기본 자료형을 문자열로 변환하는 메소드
// 기본 자료형을 String타입으로 변환한다. public static String valueOf(char c) public static String valueOf(int i) public static String valueOf(long l) public static String valueOf(float f) public static String valueOf(double d) public static String valueOf(Object obj) public static String valueOf(char[] data) public static String valueOf(char[] data, int offset, int count)
String으로 변환만 해놓고 별도의 문자열과 합치는 과정이 없을 경우에는 valueOf()메소드를 사용하는 것을 권장한다.
valueOf(Object obj)로 객체가 매개 변수로 넘어왔을 경우, "null"이라는 문자열을 리턴해준다.
toString 메소드는 매개 변수가 null객체인 경우에는 사용할 수 없다. null객체인 경우 NullPointerException이 발생한다.
이러한 예외를 방지하기 위해 객체를 출력할 때는 valueOf()메소드를 사용하면 좋다.
StringBuffer, StringBuilder
immutable한 String의 단점을 보완하기 위한 클래스에는 StringBuffer와 StringBuilder가 있다.
StringBuffer : Thread safe -> 더 안전하다 -> 여러 쓰레드에서 이 인스턴스 변수를 동시에 접근하는 경우 StringBuffer사용해야만 한다. StringBuilder : Thread safe하지 않다. -> 하나의 메소드 내에서 문자열을 생성하여 더할 경우 StringBuilder사용해도 전혀 상관없다. 공통점 - append() 사용 - 두 클래스는 문자열을 더하더라도 새로운 객체를 생성하지 않는다. - 두 클래스는 CharSequence인터페이스를 구현했다. : 하나의 클래스를 사용하여 매개 변수로 받는 작업을 할 경우 String, StringBuilder타입으로 받는 것 보다 CharSequence타입으로 받는 것이 좋다.
JDK5이상에서는 String의 더하기 연산을 할 경우, 컴파일 할 때 자동으로 해당 연산을 StringBuilder로 변환해준다.
String 클래스를 잘 사용해야만 메모리를 효율적으로 사용할 수 있고, 여러 String을 더하는 연산이 존재할 경우에는 StringBuilder나 StringBuffer클래스를 적절하게 선택하여 활용해야 한다.
참고
자바의 신,
728x90'Programming > Java' 카테고리의 다른 글
[Java] Spring 빌드 Jar, War (0) 2024.02.29 [Java] Garbage Collection (2) 2024.02.28 [Java] Java, JVM 개념 정리 (0) 2023.04.27 [Spring Boot] Visual Studio Code - Spring boot 세팅 (0) 2023.03.03 [Java] Visual Studio code Java 설치 (0) 2022.09.23