본문 바로가기

TIL/Java

[java] API - 2. new String, equals, split, StringTokenizer, 이스케이프문자

문자열 객체 사용하는 방법

 

"" 리터럴형태

- 동일한 값을 가지는 인스턴스를 단일 인스턴스로 관리한다. (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