String 클래스
특징
immutable한 Object
- immutable : 불변의
- 한 번 생성되면 더 이상 그 값을 변경할 수 없음
즉, String 문자열을 더할 경우 새로운 String 객체가 생성되고 기존 객체는 버려짐
- 기존 객체는 버려지며, 나중에 GC(Garbage collection)의 대상이 됨
자주 쓰이는 생성자
String Object는 대부분 ""로 생성하기 때문에 굳이 생성자를 사용하지는 않음
아래 생성자들은 한글을 사용하는 우리나라에서 자주 사용하는 생성자
// 현재 사용중인 플랫폼의 charset을 이용하여 제공된 byte array를 decoding한 String Object 생성
String(byte[] bytes)
// 지정한 charset을 이용하여 제공된 byte array를 decoding한 String Object 생성
String(byte[] bytes, String charsetName)
String을 byte Array로 변환
// Default CharSet의 byte Array를 생성
byte[] getBytes()
// 지정한 Charset Type으로 Byte Array 생성
byte[] getBytes(Charset charset)
// 지정한 이름의 Charset을 갖는 Byte Array 생성
byte[] getBytes(String charset)
java.nio.Charset 클래스 API - Standard charsets
US-ASCII | Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set |
ISO-8859-1 | ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1 |
UTF-8 | Eight-bit UCS Transformation Format |
UTF-16BE | Sixteen-bit UCS Transformation Format, big-endian byte order |
UTF-16LE | Sixteen-bit UCS Transformation Format, little-endian byte order |
UTF-16 | Sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order mark |
객체의 Null 체크
Object==Null && Object!=Null
길이 확인
int length()
jamieStr.length();
비어있는지 확인
boolean isEmpty();
jamieStr.length()==0;
jamieStr.isEmpty(); // 간단
같은지 비교
boolean equals(Object anObject)
boolean equalsIgnoreCase(String anotherStr) // 대소문자 구분 X
/* sorting시 주로 사용
* 비교하려는 매개 변수가 알파벳 순으로 앞이라면 양수, 뒤라면 음수 리턴
* 알파벳 순서만큼 숫자값 증가
*/
int compareTo(String anotherStr)
int compareToIgnoreCase(String str) // 대소문자 구분 X
// CharSequence or StringBuffer 객체와 String 비교
boolean contentEqauls(CharSequence cs)
boolean contentEqauls(SpringBuffer sb)
위치 찾기
// 왼쪽부터 검사
int indexOf(int ch)
int indexOf(int ch, int fromIndex)
int indexOf(String str)
int indexOf(String str, int fromIndex)
// 오른쪽부터 검사
int lastIndexOf(int ch)
int lastIndexOf(int ch, int fromIndex)
int lastIndexOf(String str)
int lastIndexOf(String str, int fromIndex)
/* Java Index는 0부터 시작함, FromIndex = 몇 번째부터 검사할지
* 포함되어 있지 않다면 둘 다 -1을 리턴
*/
특정 조건에 맞는 문자열이 있는지 확인
// 매개 변수 값으로 시작하는지 검증
boolean startsWith(String prefix)
boolean startsWith(String prefix, int toffset)
// 매개 변수 값으로 끝나는지 검증
boolean endsWith(String suffix)
// 매개 변수 값이 문자열에 존재하는지 확인
boolean contains(CharSequence s)
// 매개 변수 정규식이 문자열에 매칭되는지 확인
boolean matches(String regex)
/* 특정 영역이 매개 변수로 넘어온 문자열과 동일한지 확인
* ignoreCase : true인 경우 대소문자 구분을 하지 않고 값을 비교
* toffset : 비교 대상 문자열의 확인 시작 위치 지정, 음수면 false, toffset+len > 비교대상이면 false
* other : 존재하는지 확인할 문자열
* ooffset : other 객체의 확인 시작 위치를 지정, 음수면 false, ooffset+len > other이면 false
* len : 비교할 char의 개수를 지정
*/
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
boolean regionMatches(int toffset, String other, int ooffset, int len)
일부 추출
char
// 특정 위치의 char 값 리턴
char charAt(int index)
// 지정된 index부터 offset이 설정된 index를 리턴 - 문자열 인코딩과 관련된 문제를 해결하기 위해 사용
int offsetByCodePoints(int index, int codePointOffset)
char Array → String
// char 배열을 문자 값으로 변환
static String copyValueOf(char[] data)
// char 배열을 문자 값으로 변환, 단 offset ~ count까지의 개수만큼
static String copyValueOf(Char[] data, int offset, int count)
String → Char Array
// 문자열을 char 배열로 변환
char[] toCharArray()
String 일부 자르기
// beginIndex ~ 끝까지 String을 잘라 String으로 리턴
String substring(int beginIndex)
/* beginIndex ~ endIndex까지 String을 잘라 String으로 리턴
* 단, endIndex >= beginIndex
* 그렇지 않으면 StringIndexOutOfBoundsException 발생
*/
String substring(int beginIndex, int endIndex)
// beginIndex ~ endIndex까지 String을 잘라 CharSequence 타입으로 리턴
CharSequence subSequence(int beginIndex, int endInex)
String을 여러 개의 String Array로 나누기
// regex에 있는 정규 표현식에 맞추어 String을 잘라 String Array로 리턴
String[] split(String regex)
// regex에 있는 정규 표현식에 맞추어 String Array로 리턴, 단 limit보다 배열의 크기가 클 수 없음
String[] split(String regex, int limit)
/* 정규식을 사용하지 않고 특정 String으로 나눈다면 StringTokenizer 클래스를 사용하는 것이 편함
* 특정 알파벳이나 기호 하나로 나눈다면, split()이던 StringTokenizer던 상관 없음
*/
String 값 변경
공백 제거
// 앞 뒤의 공백을 제거한 String 리턴
String trim()
내용 대치(replace)
// oldChar의 값을 newChar로 대치
String replace(char oldChar, char newChar)
// target과 같은 값을 replacement로 대치
String replace(CharSequence target, CharSequence replacement)
// regex에 표현된 정규표현식에 포함되는 모든 내용을 replacement로 대치
String replaceAll(String regex, String replacement)
// regex에 표현된 정규표현식에 포함되는 첫번째 내용을 replacement로 대치
String replaceFirst(String regex, String replacement)
형식에 맞춰 값을 치환
// format 중 변환해야 하는 부분을 args로 변환
static String format(String format, Object... args)
// 출력만 하려면 아래 메서드 이용해도 상관 없음
System.out.format()
/* 매개 변수 수 < 변경해야 할 대상 수
* java.util.MissingFormatArgumentException
*/
대소문자 변경
// 소문자로
String toLowerCase()
// 대문자로
String toUpperCase()
자료형을 String으로 변환
static String valueOf(boolean b)
static String valueOf(char c)
static String valueOf(char[] data)
static String valueOf(char[] data, int offset, int count)
static String valueOf(double d)
static String valueOf(float f)
static String valueOf(int i)
static String valueOf(long l)
// 객체가 null이라면 "null"이라는 String을 리턴함
static String valueOf(Object obj)
/* +"" vs valueOf
* 아래 두 개는 결과는 같지만, 별도의 문자열과 합치는 과정이 없을 경우엔 valueOf 사용 권장
*/
String.valueOf(jamieStr);
jamieStr+"";
주의, 사용하지 말 것 - intern()
C로 구현되어 있는 native 메서드 중 하나
시스템의 심각한 성능 저하를 발생시킬 수도 있음
- 억지로 Constant pool에 값을 할당하도록 만드므로, 저장되는 영역은 한계가 있으므로 그 영역에 대해서 메모리를 지우는 단계를 거치게 됨
- equlals() 보다 ==이 빠르지만, 이 작은 차이를 위해서 intern()을 사용하기엔 매우 비생산적
// Constant pool에 해당 값이 없으므로 새로 생성
String jamieStr1 = "Jamie";
// 같은 문자열이 Constant pool에 있으므로 해당 값을 사용
String jamieStr2 = "Jamie";
// 즉 jamieStr1==jamieStr2
System.out.println(jamieStr1==jamieStr2); // true
// 같은 문자열이 있건 말건 새로운 객체 생성
String jamieStr3 = new String("Jamie");
// 즉 jamieStr1!=jamieStr3
System.out.println(jamieStr1==jamieStr3); // false
// 같은 문자열이 있건 말건 새로운 객체 생성
String jamieStr4 = new String("Jamie");
/* intern()은 풀에 해당 값이 있으면, 풀에 있는 값을 리턴, 없다면 풀에 해당 값을 추가
* 성능에 악영향을 끼치는 부분
*/
jamieStr4 = jamieStr4.intern();
// 즉 jamieStr1==jamieStr4
System.out.println(jamieStr1==jamieStr4); // true
StringBuffer와 StringBuilder
immutable한 String의 단점을 보완하기에 나온 클래스
- 문자열을 더하더라도 새로운 객체를 생성하지 않음
append() 메서드
매개 변수로 모든 기본 자료형과 참조 자료형 사용 가능
StringBuilder jamieSb = new StringBuidler();
jamieSb.append("Hello");
jamieSb.append(" world");
jamieSb.append(" Hello").append(" world");
특징
JDK 5 ~ String의 더하기 연산시, 컴파일할 때 자동으로 해당 연산은 StringBuilder로 변환해줌
- 일일이 더하는 작업을 변환해줄 필요는 없음
- for 루프와 같은 반복 연산시에는 자동 변환이 안되므로 꼭 필요함
공통점
모두 문자열을 다룸
CharSequence 인터페이스를 구현
= String / StringBuffer / StringBuilder를 사용하여 매개 변수로 받는 작업을 할 때 CharSequence 타입으로 받는 것이 좋음
차이점
StringBuffer == Thread Safe (더 안전함)
- 어떤 클래스에 문자열을 생성하여 더하기 위한 문자열을 처리하기 위한 인스턴스 변수가 선언
- 어떤 쓰레드에서 해당 변수를 동시에 접근하는 경우
StringBuilder != Thread Safe (속도는 더 빠름)
- 하나의 메서드 내에서 문자열을 생성하여 더할 경우