문자열 객체 사용하는 방법
"" 리터럴형태
- 동일한 값을 가지는 인스턴스를 단일 인스턴스로 관리한다. (singleton)
new String("문자열")
-매번 새로운 인스턴스를 생성한다
String str1 = "java";
String str2 = "java";
String str3 = new String("java");
String str4 = new String("java");
리터럴 형태로 만든 문자열 인스턴스는 동일한 값을 가지는 인스턴스로 하나의 인스턴스로 관리한다.
- 따라서 주소 값을 비교하는 == 연산으로 비교 시 서로 동일한 주소를 비교하여 true를 반환한다.
- new로 새로운 인스턴스를 생성하게 되면 기존 인스턴스를 두고 새로운 인스턴스를 할당했기 때문에 == 연산으로 비교 시 서로 다른 주소값을 가지고 있기 때문에 false를 반환한다.
- 동일한 방식으로 인스턴스를 생성하고 값 또한 같더라도 새로운 인스턴스를 생성하는 방식은 서로 다른 주소를 가지기 때문에 false를 반환한다.
- 하지만 이 4개의 문자열은 동일한 hashCode값을 가진다. 동일한 문자열은 동일한 hashCode값을 반환한다.
System.out.println("str1 == str2 : " + (str1 == str2)); //true
System.out.println("str2 == str3 : " + (str2 == str3)); //false
System.out.println("str3 == str4 : " + (str3 == str4)); //false
equals()
- String클래스의 equals() 메소드는 인스턴스 비교가 아닌 문자열 값을 비교하여 동일한 값을 가지는 경우 true, 다른 값을 가지는 경우 false를 반환하도록 Object의 equals() 메소드를 재정의 해 두었다.
따라서 무자열 인스턴스 생성 방식과 상관 없이 동일한 문자열인지 비교하기 위해 == 연산 대신 equals() 메소드를 써야 한다.
System.out.println("str1.equals(str3) : " + str1.equals(str3)); //true
System.out.println("str3.equals(str4) : " + str3.equals(str4)); //true
split()과 StringTokenizer
split은 정규표현식 이용(문자열 패턴), StringTokenizer는 구분자 문자열 이용
각 문자열의 의미는 사번/이름/주소/부서 를 의미한다.
String emp1 = "100/홍길동/서울/영업부"; //모든 값 존재
String emp2 = "200/유관순//총무부"; //주소 없음
String emp3 = "300/이순신/경기도"; //부서 없음
먼저 split을 이용해서 3명의 문자열을 정보별로 분리한다.
String[] empArr1 = emp1.split("/");
String[] empArr2 = emp2.split("/");
String[] empArr3 = emp3.split("/");
for(int i = 0; i < empArr1.length; i++) {
System.out.println("empArr1[" + i + "] : " + empArr1[i]); //정상 출력
}
for(int i = 0; i < empArr2.length; i++) {
System.out.println("empArr2[" + i + "] : " + empArr2[i]); //중간 값 빈 문자열
}
for(int i = 0; i < empArr3.length; i++) {
System.out.println("empArr3[" + i + "] : " + empArr3[i]); //마지막 값 출력 안됨
}
출력값=>
empArr1[0] : 100
empArr1[1] : 홍길동
empArr1[2] : 서울
empArr1[3] : 영업부
empArr2[0] : 200
empArr2[1] : 유관순
empArr2[2] :
empArr2[3] : 총무부
empArr3[0] : 300
empArr3[1] : 이순신
empArr3[2] : 경기도
마지막 구분자 사이에 값이 존재하지 않는 경우 이후 값도 추출하고 싶을 때
몇 개의 토큰으로 분리할 것인지 한계치를 두번째 인자로 넣어줄 수 있다.
이 때 음수를 넣게 되면 마지막 구분자 뒤의 값이 존재하지 않는 경우 빈 문자열로 토큰을 생성한다.
String[] empArr4 = emp3.split("/", -1);
for(int i = 0; i < empArr4.length; i++) {
System.out.println("empArr4[" + i + "] : " + empArr4[i]);
}
출력값=>
empArr4[0] : 300
empArr4[1] : 이순신
empArr4[2] : 경기도
empArr4[3] :
StringTokenizer의 경우 공백으로 존재하는 값을 무시해버린다.
StringTokenizer st1 = new StringTokenizer(emp1, "/");
StringTokenizer st2 = new StringTokenizer(emp2, "/");
StringTokenizer st3 = new StringTokenizer(emp3, "/");
while(st1.hasMoreTokens()) {
System.out.println("st1 : " + st1.nextToken());
}
while(st2.hasMoreTokens()) {
System.out.println("st2 : " + st2.nextToken());
}
while(st3.hasMoreTokens()) {
System.out.println("st3 : " + st3.nextToken());
}
st1 : 100
st1 : 홍길동
st1 : 서울
st1 : 영업부
st2 : 200
st2 : 유관순
st2 : 총무부
st3 : 300
st3 : 이순신
st3 : 경기도
nextToken()으로 토큰을 꺼내면 해당 StringTokenizer의 토큰을 재사용하는 것이 불가능하다.
while(st1.hasMoreTokens()) {
System.out.println("st1 : " + st1.nextToken());
} //출력안됨
String colorStr = "red*orange#blue/yellow green";
"*#/" 이라는 문자열이 구분자로 존재하지 않아서 에러 발생
//String[] colors = colorStr.split("*#/ ");
대괄호로 묶은 문자열은 문자열이 아닌 각 문자들의 패턴으로 볼 수 있다.
따라서 순서 상관 없이 존재하는 문자들을 이용해서 구분자로 사용할 수 있다.
String[] colors = colorStr.split("[/*# ]");
for(int i = 0; i < colors.length; i++) {
System.out.println("colors[" + i + "] : " + colors[i]);
}
출력값=>
colors[0] : red
colors[1] : orange
colors[2] : blue
colors[3] : yellow
colors[4] : green
StringTokenizer의 두번째 인자 문자열 자체는 연속된 문자열이 아닌 하나하나를 구분자로 이용하겠다는 의미이다.
StringTokenizer colorStringTokenizer = new StringTokenizer(colorStr, "*#/ ");
while(colorStringTokenizer.hasMoreTokens()) {
System.out.println(colorStringTokenizer.nextToken());
}
출력값=>
red
orange
blue
yellow
green
개행문자
System.out.println("안녕하세요.\n저는 홍길동입니다.");
탭문자
System.out.println("안녕하세요.\t저는 홍길동입니다.");
홑 따옴표 문자
System.out.println("안녕하세요. 저는 '홍길동'입니다."); //이스케이프 문자 안 써도됨
//System.out.println('''); //홑 따옴표 문자와 문자 리터럴 기호가 중복됨
System.out.println('\''); //출력하고싶은 ' 앞에 \ 넣어줌
쌍 따옴표 문자
//System.out.println("안녕하세요 저는 "홍길동" 입니다."); //문자열 리터럴과 기호가 중복됨
System.out.println("안녕하세요 저는 \"홍길동\"입니다."); //이스케이프 문자를 사용해서 구분함
역슬래쉬 문자
//System.out.println("안녕하세요 저는 \홍길동\ 입니다."); //역슬래쉬를 표현하고 싶지만 에러 발생(이스케이프 문자 예약문자와 겹침)
System.out.println("안녕하세요 저는 \\홍길동\\ 입니다."); //이스케이프 문자를 사용해서 구분함
이러한 특수문자나 특수한 기능을 표현하는 문자를 이스케이프 문자라고 한다.
split시 이스케이프 문자를 사용해야 하는 특수문자도 존재한다.
이스케이프 문자 사용 안 한 특수문자
~ ` ! @ # % & - _ = ; : ' / " , < > /
이스케이프 문자를 사용하는 특수문자
$ ^ * ( _+ | { } [ ] . ?
String str = "java$oracle$jdbc";
String[] sarr = str.split("\\$");
for(String s : sarr) {
System.out.println(s);
}
출력값=>
java
oracle
jdbc