매개변수가 있는 생성자를 호출하고 싶다면 리플렉션을 이용해서 Constructor 객체를 얻어야 한다.
추상 클래스나 인터페이스를 이용해 인스턴스를 만드려하면 InstantiationException 예외가 발생한다.
클래스나 생성자가 접근 제한자로 인해 접근할 수 없다면 IllegalAccessException 예외가 발생한다.
메소드의 반환 타입이 Object라서 강제 형변환을 해야 하는데, 보통 인터페이스를 이용한 다형성으로 처리한다.
String 클래스
java.lang 패키지에 속해있다.
문자열 리터럴은 자동으로 String 객체로 생성된다.
Deprecated된 생성자 외에도 13개의 생성자를 더 제공한다.
파일의 내용을 읽거나, 네트워크를 통해 받은 데이터는 보통 byte[] 이므로 이것을 문자열로 변환하기 위해 사용한다.
키보드에서 문자열을 입력받아 출력하는 생성자 예제 코드
.charAt() 메소드
char / 특정 위치의 문자를 반환한다.
.equals() 메소드
boolean / 두 문자열을 비교한다.
.getBytes() 메소드
byte[] / 문자열을 바이트 배열로 반환한다.
인자로 UTF-8 같은 캐릭터셋 유형을 주면, 해당 캐릭터셋에 맞게 반환해준다.
네트워크로 문자열을 전송하거나, 문자열을 암호화할 때 유용하다.
EUC-KR 문자셋을 이용하여 인코딩하면 영어 1바이트 한글 2바이트가 된다. UTF-8 문자셋을 이용하여 인코딩하면 영어 1바이트 한글 3바이트가 된다. 기본 값은 시스템의 기본 문자셋을 이용한다. 존재하지 않는 문자셋을 입력하면 java.io.UnsupportedEncodingException 예외가 발생한다.
.indexOf() 메소드
문자열 내에서 주어진 문자열의 위치를 인덱스 기준의 숫자로 반환한다.
없으면 -1 반환
.length() 메소드
총 문자열의 길이를 반환한다.
.replace() 메소드
인자로 target과 replacement를 받아서 target이 replacement로 대체된 결과 문자열을 반환한다.
.substring()
지정된 위치에서 끝까지 잘라낸 새로운 문자열을 반환한다.
인자를 2개 주면 두번째 인자까지 잘라낸 새로운 문자열을 반환한다.
toLowerCase(), toUpperCase()
대문자 혹은 소문자로 변환한다.
대소문자 문자 비교 때는 .equalsIgnoreCase() 메소드를 이용하면 대소문자 무시 비교를 할 수 있다.
trim()
앞뒤 공백을 제거한 문자를 반환한다.
valueOf()
기본 타입값을 문자열로 반환한다.
StringTokenizer 클래스
주로 문자열이 특정한 구분자(delimiter)로 연결된 구조일 때, 특정한 구분자를 기준으로 문자열을 분리할 때 사용된다.
String 클래스에도 .split() 메소드가 있어서 특정 구분자를 기준으로 문자열을 나눌 수 있지만, 정규표현식을 이용해야 한다. StringTokenizer 클래스가 제공하는 .split()은 단순히 문자 delimeter만 구분해서 나누는 방식이다.
String.split()
위와 같이 정규표현식을 이용하여 구분할 수 있다. 예제 문자열은 이름이 , 혹은 -로 구분되어 있는데, 두 문자를 모두 구분자로 이용하기 위한 정규표현식이 ",|-"라는 문자열로 표현되었다.
StringTokenizer 생성자
문자열이 한 종류의 구분자로 되어있을 때 용이하며, 말 그대로 문자열을 토큰화한다. 토큰화한 문자열을 다루기 위해 3가지 내장 메소드를 제공한다.
int countTokens(): 꺼내지 않고 남아있는 토큰의 수를 반환한다.
boolean hasMoreTokens(): 남아 있는 토큰이 있는지 여부에 대해 반환한다.
String nextToken(): 토큰을 하나씩 꺼내온다.
토큰이 남아있지 않다면, NoSuchElementException 예외를 발생시킨다.
StringBuffer, StringBuilder 클래스
필요성
String은 구조적으로는 내부의 문자열을 수정할 수 없다. 단, 새로운 문자열을 String 타입의 변수에 할당함으로써, 새로운 문자를 저장할 수 있다.
이를테면 String.replace()는 내부의 문자를 변경하는 것이 아니라, 변경된 새로운 문자열을 반환하는 것이다. String 타입끼리의 + 연산도 마찬가지이다.
이러한 방식의 단점은 아무래도 많은 문자열 변환 연산이 있을 때, 속도가 현저히 느려질 수 있다는 단점이 있다.
문자열 변경 작업이 많을 때, 그로 인한 속도 저하를 막기 위해 StringBuffer 혹은 StringBuilder 클래스가 이용되는 것이다.
위 두 클래스는 내부 버퍼(데이터를 임시로 저장하는 메모리)에 문자열을 저장해두고 그 안에서 추가, 수정, 삭제 작업을 할 수 있도록 설계되어 있다.
String타입처럼 새로운 문자열 객체를 만들어내고 다시 저장하는 방식이 아니라 진짜 기존의 문자열을 수정하는 방식이다.
두 클래스의 차이점
기본적으로 StringBuffer와 StringBuilder의 사용 방법은 동일하다.
StringBuffer는 멀티 스레드 환경에서 사용할 수 있도록 동기화가 적용되어 있어 스레드에 안전하다.
StringBuilder는 단일 스레드 환경에서만 사용하도록 설계되어 있다.
생성자
StringBuilder(): 기본 생성자는 16개의 문자를 저장할 수 있는 초기 버퍼를 만든다.
StringBuilder(int capacity): capacity 만큼의 초기 버퍼를 만든다.
사실 버퍼가 부족하면 버퍼 크기를 자동으로 늘리기 때문에 초기 버퍼 사이즈가 크게 중요하진 않다.
메소드들
append(...): 문자열 끝에 매개값을 추가한다.
insert(int offset, ...): offset으로 지정된 자리에 매개값을 추가한다.
delete(int start, int end): 문자열의 일부분을 삭제한다.
deleteCharAt(int index): 문자열에서 주어진 index의 문자를 삭제한다.
replace(int start, int end, String str): 문자열의 일부를 다른 문자열로 변환한다.
reverse(): 문자열의 순서를 뒤바꾼다.
setCharAt(int index, char ch): 문자열에서 주어진 index의 문자를 다른 문자로 바꾼다.
append()와 insert() 메소드는 다양한 타입으로 오버로딩되어 있어서 다양한 타입을 문자로 추가, 삽입할 수 있다.