String 클래스
String 클래스를 API문서와 클래스를 직접 확인해보면 위와같이 선언되어 있는 것을 볼 수 있습니다.
- final로 선언되어 있고
- Object 를 상속받으며
- Serializable, Comparable<String> CharSequence 인터페이스를 구현하고 있는 구현체입니다.
final로 선언되어 있으니 String 클래스는 상속이 불가능하고, 자바의 모든 클래스는 Object로 부터 상속받니 이것은 당연한(?)사실입니다.
그렇다면 인터페이스가 궁금해집니다.
먼저, Serializable은 '구현해야 하는 메소드가 하나도 없는 특이한 인터페이스' 입니다.
이 인터페이스로 선언하면, 해당 객체를 다른 서버로 전송 가능하거나 파일로 저장이 가능한 상태가 됩니다.
그리고 Comparable은 이름에서 알 수 있듯이 비교를 하기위한 인터페이스로, compareTo() 메소드 하나만 선언되어 있습니다.
뒤에는 <String> 제네릭으로 선언되어 타입 오류에 대한 방지 또한 해주고 있습니다.
객체.compareTo(비교대상) 형태로 사용하여 객체가 더 크면 양수를 리턴하고, 같으면 0, 작으면 음수를 리턴합니다.
초기에 compareTo를 익힐 때 빼기로 이해하면 편하다하여 이 방식으로 익힌 뒤로 헷갈리지 않고 있습니다.
마지막으로 CharSequence는 해당 클래스가 문자열을 다루기 위한 클래스라는 것을 명시적으로 나타내는데 사용됩니다.
생성자
String의 생성자는 사용금지된 deprecated를 제외하면 아래와 같습니다.
생성자 | 설명 |
String() | 빈 String 객체를 생성합니다. |
String(byte[] bytes) | 현재 사용중인 플랫폼의 캐릭터 셋을 사용하여 byte배열을 디코딩한 String 객체를 생성합니다. |
String(byte[] bytes, Charset charset) | 지정된 캐릭터셋을 사용하여 byte배열을 디코딩한 String 객체를 생성합니다. |
String(byte[] bytes, String charsetName) | 지정한 이름을 갖는 캐릭터셋을 사용하여 byte배열을 디코딩한 String 객체를 생성합니다. |
String(byte[] bytes, int offset, int length) | 현재 사용중인 플랫폼의 캐릭터 셋을 사용하여 제공된 byte배열의 일부(offset부터 시작하여 length개의 바이트)를 디코딩한 String 객체를 생성합니다. |
String(byte[] bytes, int offset, int length, Charset charset) | 지정된 캐릭터셋을 사용하여 제공된 byte배열의 일부(offset부터 시작하여 length개의 바이트)를 디코딩한 String 객체를 생성합니다. |
String(byte[] bytes, int offset, int length, String charsetName) | 지정한 이름을 갖는 캐릭터셋을 사용하여 제공된 byte배열의 일부(offset부터 시작하여 length개의 바이트)를 디코딩한 String 객체를 생성합니다. |
String(char[] value) | char 배열의 내용을 붙여서 String 객체를 생성합니다. |
String(char[] value, int offset, int count) | 위 메소드와 동일하나, offset부터 count개의 문자만 잘라 String 객체를 생성합니다. |
String(int[] codePoints, int offset, int count) | 유니코드 코드 포인트 배열의 특정 부분(offset부터 시작하여 count개의 코드 포인트)을 사용하여 문자열을 생성합니다. |
String(String original) | 매개변수로 넘어온 문자열과 동일한 내용의 새로운 String 객체를 생성합니다. |
String(StringBuffer buffer) | StringBuffer 객체의 내용으로 문자열을 생성합니다. |
String(StringBuilder builder) | StringBuilder 객체의 내용으로 문자열을 생성합니다. |
프로그래밍에서 알파벳을 제외한 문자를 표현할 때에는 캐릭터셋으로 표현해야 합니다.
한글도 알파벳이 아니기 때문에 고유한 캐릭터셋이 있습니다.
요즘은 많이 없지만 예전에는 간혹가다 웹페이지에서 한글이 깨지는 경우를 볼 수 있었습니다.(ex. 쏙옙..등..)
이렇게 한글이 깨지는 이유는 브라우저 캐릭터셋과 웹페이지에 지정된 캐릭터셋이 같지 않기 때문입니다.
java.nio 패키지의 Charset 클래스 API에 보면 표준 캐릭터셋을 아래와 같이 정의하고 있습니다.
한글과 같은 비라틴(Non-Latin Alphabet) 문자는 다양한 언어의 문자를 표현하기 위한 국제표준 약속인 유니코드(UniCode)에 정의되어 있습니다.
위 정의에서 UCS라는 것이 보이는데 이는 Unicode Character Set의 약자입니다.
즉, UCS를 변환하는 포맷인 UTF-8, UTF-16을 사용하여 한글을 처리할 수 있습니다.
예전에는 UTF-8, EUC-KR을 많이 사용했지만 요즘은 UTF-16을 대부분 사용한다고 합니다.
(API에서는 EUC-KR조차 없습니다.)
문자열을 다른 캐릭터셋으로 변환해보기
먼저 문자열을 byte 배열로 바꾸기 위해서는 아래와 같은 메소드가 있습니다.
리턴타입 | 메소드 | 설명 |
byte[] | getBytes() | 기본 캐릭터셋의 바이트 배열 생성 |
byte[] | getBytes(Charset charset) | 지정한 캐릭터셋 객체 타입으로 바이트 배열 생성 |
byte[] | getBytes(String charsetName) | 지정한 이름의 캐릭터셋을 갖는 바이트 배열 생성 |
String 객체를 하나 만들어 첫번째 메소드를 사용해 byte 배열로 바꾸어 줄 것입니다.
그리고 생성자를 이용해서 byte 배열을 UTF-8, EUC-KR 캐릭터셋으로 합쳐 보겠습니다.
예시 코드
public class StringExample {
public static void main(String[] args) {
StringExample example = new StringExample();
example.constructors();
}
public void constructors() {
try {
String str = "테스트";
byte[] array1 = str.getBytes(); // 문자열을 byte로 변환
printByteArray(array1); // byte값 출력
String str1 = new String(array1, "UTF-8");// byte 배열을 합쳐서 문자열로 만듬
System.out.println(str1); // 출력
byte[] array2 = str.getBytes();
printByteArray(array2);
String str2 = new String(array2, "EUC-KR"); // EUC-KR 캐릭터셋으로 String 생성
System.out.println(str2);
} catch (Exception e) {
e.printStackTrace();
}
}
public void printByteArray(byte[] array) {
for (byte data : array) {
System.out.print(data + " ");
}
System.out.println();
}
}
결과
아래 EUC-KR 캐릭터셋은 글자가 깨졌습니다. 이는 현재 설정에서 제공하는 캐릭터셋이 UTF-8 이기 때문입니다.
byte배열 변환은 UTF-8 로 되었지만, String str2 = new String(array2, "EUC-KR"); 에서 다른 캐릭터셋으로 합치니 제대로 되지 않은 것입니다.
즉, getBytes() 메소드는 기본 설정되어 있는 캐릭터셋으로 변환하므로 외부로 값을 보내는 경우 캐릭터셋을 지정해주는 것이 좋다고 합니다.
byte[] array2 = str.getBytes("EUC-KR");
이렇게 캐릭터셋을 지정해주면 아래와 같이 정상적으로 출력됨을 확인할 수 있습니다.
메소드를 try - catch로 감싼 이유는 String 생성자에서 지정되지 않은 캐릭터셋인 경우 UnsupportedEncodingException이 발생하기 때문입니다.
'Language > JAVA' 카테고리의 다른 글
자바 제네릭(Generic) 타입에 대하여 (0) | 2024.07.23 |
---|---|
String 클래스 파고들기 - 객체의 특성 및 더하기 연산의 버전별 차이 (0) | 2024.04.09 |
자바가 돌아가는 동작 원리 (0) | 2024.03.06 |
자바에서의 Call by value 와 Call by reference (1) | 2024.03.06 |
기본형 타입과 참조형 타입 (0) | 2023.02.21 |
남에게 설명할 때 비로소 자신의 지식이 된다.
포스팅이 도움되셨다면 하트❤️ 또는 구독👍🏻 부탁드립니다!! 잘못된 정보가 있다면 댓글로 알려주세요.