다른 언어에서는 문자열을 char형의 배열로 다루기도 하는데 자바에서는 문자열을 위한 클래스를 제공한다.
바로 String 클래스이다.
String 클래스는 자주 사용되고 중요한 클래스이므로 이번에 잘 정리해야겠다.
String hi = "hi";
String there = "there";
hi = hi + there;
'+' 연산자를 이용해서 문자열을 결합하는 경우 인스턴스 내의 문자열이 바뀌는 것이 아니다.
문자열 "hithere"인 새로운 String 인스턴스가 생성되는 것이다.
따라서, '+' 연산자를 사용해서 문자열을 결합하면 연산 마다 새로운 문자열을 가진
String 인스턴스가 생성되어 메모리공간을 차지하게 되므로 가능한 결합횟수를 줄이는 것이 좋다.
문자열을 만드는 방법은 두 가지이다.
String s1 = "hi"; // 문자열 리터럴 "hi"의 주소가 s1에 저장
String s2 = "hi"; // 문자열 리터럴 "hi"의 주소가 s2에 저장
String s3 = new String("hi"); // 새로운 String 인스턴스 생성
String s4 = new String("hi"); // 새로운 String 인스턴스 생성
두 방식의 차이점은 String 클래스 생성자를 이용한 경우에는 항상 새로운 String 인스턴스가 생성되지만
문자열 리터럴은 이미 존재하는 것을 재사용한다.
s1 == s2 // true
s1 == s3 // false
s3 == s4 // false
equals()를 사용하면 문자열의 내용인 "hi"를 가지고 비교해서 모두 같다는 결과가 나오기 때문에
주소를 비교하는 연산자로 비교해보면 (s1, s2)는 같고, (s1, s3) / (s3, s4)는 다르다는 결과를 알 수 있다.
public static void main(String[] args) {
String s1 = "hi";
String s2 = "hi";
String s3 = "hello";
}
위와 같이 문자열 리터럴 방식으로 코드를 작성하고 컴파일을 해보자.
// parameter args
L0
LINENUMBER 5 L0
LDC "hi"
ASTORE 1
L1
LINENUMBER 6 L1
LDC "hi"
ASTORE 2
L2
LINENUMBER 7 L2
LDC "hello"
ASTORE 3
L3
LINENUMBER 8 L3
RETURN
...
class 파일을 열어본 결과 클래스 파일에 문자열 리털("hi", "hello)이 저장되어 있는것을 확인할 수 있다.
이와같이 String 리터럴들은 컴파일시에 클래스파일에 저장된다.
코드를 실행하면 "hi", "hello"를 담고 있는 String 인스턴스가 하나씩 생성된 후,
참조변수들은 아래와같이 각각을 참조하게 된다.
정리하자면 위의 컴파일된 클래스 파일이 클래스 로더에 의해 메모리에 올라갈 때, 리터럴 목록에 있는 리터럴들이
JVM내에 있는 '상수풀(constant pool)'
에 저장되는데
이 때, "hi"와 같은 문자열 리터럴이 자동적으로 생성되어 저장되는 것이다.
String s = "";
위의 코드는 String 인스턴스 내부에 'new char[0]' 와 같이 길이가 0인 char형 배열을 저장하고 있는것과 같다.
자주 사용될만한 String 클래스의 생성자와 메소드에 대해 알아보자.
간단하게 사용법위주로 정리했다.
char[] c = {'H', 'e', 'l', 'l', 'o'};
String hello = new String(c);
c = hello.toCharArray();
char c1 = "hello".charAt(1); // 'e'
int i = "aaa".compareTo("aaa"); // 0
int i2 = "aaa".compareTo("bbb"); // -1
int i3 = "bbb".compareTo("aaa"); // 1
String helloWorld = "Hello".concat(" World");
boolean result = helloWorld.contains("lo"); // true
String file = "Hello.jpg";
boolean b = file.startsWith("Hello"); // true
String file = "Hello.jpg";
boolean b = file.endsWith("jpg"); // true
boolean b = "hello".equalsIgnoreCase("HELLO"); // true
int index = hello.indexOf('l'); // 2
int index = hello.indexOf('e', 0); // 1
int index2 = hello.indexOf('e', 2); // -1
String s = "HI THERE"
int idx = s.indexOf("THERE"); // 3
String s = "java.lang.String";
int idx = s.lastIndexOf('.'); // 10
int idx2 = s.indexOf('.'); // 4
String s = "Hello".length(); // 5
String books = "JPA, SPRING, JAVA";
String[] arr = books.split(","); // [JPA, SPRING, JAVA];
String s = "java.lang.Object";
String object = s.substring(10); // Object
String lang = s.substring(5, 9)); // lang
String lower = "HellO".toLowerCase(); // hello
String upper = "heLLo".toLowerCase(); // HELLO
String trim = " hi hello ".trim(); // hi hello
String b = String.valueOf(true);
String i = String.valueOf(100);
String c = String.valueOf('a');
String l = String.valueOf(100L);
String d = String.valueOf(100.0);
join()은 여러 문자열 사이에 구분자를 넣어서 결합한다.
구분자로 문자열을 자르는 split()과 반대되는 작업이다.
String coffees = "latte, americano, mocha";
String[] arr = coffees.split(",");
String str = String.join("/", arr); // latte/americano/mocha
StringJoiner클래스를 사용해서 문자열을 결합할 수도 있다.
StringJoiner sj = new StringJoiner("/", "[", "]");
for (String s : arr) {
sj.add(s.toUpperCase());
}
System.out.println(sj.toString()); // [LATTE|AMERICANO|MOCHA]
getBytes(String charsetName) 를 사용하면 문자열의 문자 인코딩을 다른 인코딩으로 변경 가능하다.
public static void main(String[] args) {
String han = "한";
byte[] bArr = han.getBytes(StandardCharsets.UTF_8);
byte[] bArr2 = han.getBytes(StandardCharsets.UTF_16);
System.out.println("UTF-8:" + joinByteArr(bArr));
System.out.println("UTF-16:" + joinByteArr(bArr2));
System.out.println("UTF-8:" + new String(bArr, StandardCharsets.UTF_8));
System.out.println("UTF-16:" + new String(bArr2, StandardCharsets.UTF_16));
}
private static String joinByteArr(byte[] bArr) {
StringJoiner sj = new StringJoiner(":", "[", "]");
for (byte b : bArr) {
sj.add(String.format("%02X", b));
}
return sj.toString();
}
UTF-8:[ED:95:9C]
UTF-16:[FE:FF:D5:5C]
UTF-8:한
UTF-16:한
int i = 100;
String str1 = i + "";
String str2 = String.valueOf(i);
int i = Integer.parseInt("100");
int i2 = Integer.valueOf("100");
boolean b = Boolean.parseBoolean("true");
boolean b2 = Boolean.valueOf("false");