본문 바로가기
카테고리 없음

기본 API2 - String

by 낭만 코딩 2024. 9. 24.

1. 문자열 연산

2. 문자열 객체

3. String 메서드

 

 

1. 문자열 연산

String 클래스는 다른 클래스들과는 다르게 new 키워드가 아니라 ‘=’ 대입연산자로 객체를 생성할 수 있습니다. 그리고 + 더하기 연산이 가능한 클래스입니다. 기본자료형과 + 연산을 하게 되면 기본자료형도 String으로 자동 형변환이 됩니다.

 

package example;

public class StringEx {

	public static void main(String[] args) {
		
		int score = 90;
		System.out.println("당신의 점수는 " + score + "입니다."); // 자동형변환
		
		//String s = score;	// 데이터타입이 달라 에러
		String s = String.valueOf(score); // String으로 형변환
		
		String s2 = score + ""; // 문자열을 + 연산하여 String으로 형변환

	}

}

 

실행 결과

당신의 점수는 90입니다.

 

지금까지 예제들을 보면 대부분 어떤 변수에 값을 넣어 System.out.println() 메서드에서 문자열로 출력했었는데, "당신의 점수는 " 문자열에 정수 타입의 score라는 변수를 + 연산하면 문자열로 변환되어 연산이 되게 됩니다. 즉 문자열 3개를 연결해서 출력한 것입니다.

아래는 문자열 s변수에 정수값을 대입하는 코드가 있는데, 이 코드는 에러가 발생합다. 데이터 타입이 다르기 때문이죠. 그래서 바로 아래줄에 String.valueOf() 메서드를 이용해 String 타입으로 변환해서 대입하고 있습니다.

마지막 라인도 마찬가지로 정수를 문자열로 변환하는 기능을 하는데, String.valueOf() 메서드를 사용하지 않고, 앞에서 배운 문자열과 + 연산을 하면 문자열로 변환되는 것을 이용해 score + "" 코드는 문자열 + 연산으로 표현한 것입니다.

이렇게 메서드를 사용하지 않고 쉽게 문자열로 바꾸는 방법도 있습니다. 자주 사용되는 코드이니 기억해 두세요.

 

아래 예제의 결과값을 예측해보겠습니다.

package example;

public class StringEx2 {

	public static void main(String[] args) {
		
		String sum = "";
		
		for (int i=1; i<=5; i++) {
			sum += i;
		}
		System.out.println(sum);

	}

}

 

실행 결과

12345

 

변수 i1부터 5까지 총 5번 반복하면서 sum 변수에 += 대입연산 (더하고 대입)하고 있습니다. 대충 보면 1+2+3+4+5해서 15가 출력될것 같은데, "12345"가 출력되었습니다. 어떻게 된 것일까요?

 

for문 안의 반복되는 실행문 sum += i; 의 실제 실행되는 구조를 보면

sum = sum + 1;
sum = sum + 2;
sum = sum + 3;
sum = sum + 4;
sum = sum + 5;

 

sum 변수는 처음에 String 타입으로 선언된 변수이다. 문자열에 + 1을 하면 정수 1이 문자열로 변환되기 때문에 계속 문자열 연산이 수행된 것이다.

 

 

2. 문자열 객체

String 클래스의 객체를 생성하는 방법은 두가지가 있는데, new 연산자를 사용해서 다른 클래스들처럼 객체를 생성하는 방법과 = 연산자를 사용해 대입하는 방식으로 객체를 생성하는 방법이 있습니다. 아래 예제를 먼저 살펴보겠습니다.

 

package example;

public class StringEx3 {

	public static void main(String[] args) {
		
		String name1 = "홍길동";
		String name2 = "홍길동";
		
		if (name1 == name2) {
			System.out.println("name1 == name2");
		} else {
			System.out.println("name1 != name2");
		}
		
		if (name1.equals(name2)) {
			System.out.println("name1.equals(name2)");
		} else {
			System.out.println("!name1.equals(name2");
		}
		
		String name3 = new String("홍길동");
		String name4 = new String("홍길동");
		
		if (name3 == name4) {
			System.out.println("name3 == name4");
		} else {
			System.out.println("name3 != name4");
		}
		
		if (name3.equals(name4)) {
			System.out.println("name3.equals(name4)");
		} else {
			System.out.println("!name3.equals(name4");
		}

	}

}

 

실행 결과

name1 == name2
name1.equals(name2)
name3 != name4
name3.equals(name4)

 

이 예제의 결과를 보면 = 대입연산자로 객체를 생성할 때와 new 연산자로 객체를 생성할 때 결과가 다른데, 대입연산자로 객체를 생성하면 일반 객체들이 저장되는 힙(heap) 메모리 영역이 아닌 상수풀에 값이 저장됩니다.

상수 풀(Constant Pool)은 상수나 리터럴 값등을 저장하는 공간으로 메모리 절약을 위해 사용하는 공간입니다. 같은 문자열 값을 대입 연산자를 이용하여 다른 객체를 생성하면 이미 상수풀에 같은 값이 존재하므로 추가되지 않고, 기존의 주소를 참조변수에 저장하게 됩니다. 그래서 name1name2== 로 비교했을 때 true가 되는 것입니다.

그러나 new 연산자로 객체를 생성하면 상수 풀이 아닌 힙 영역에 저장되므로, new 연산자를 사용해서 객체를 생성할 때마다 새로 저장하게 됩니다. 그래서 name3name4== 비교연산의 결과가 false가 되었습니다. 하지만 앞에서 배운 String 클래스의 equals() 메서드는 오버라이딩 되어 값을 비교하도록 되어 있기 때문에, name1.equals(name2), name3.equals(name4) 모두 true 로 출력되었습니다.

 

문자열은 문자라고만 부르지 않고, 문자열이라고 부릅니다. 배열처럼 줄지어, 나열되어 있는 객체라서 문자''이라고 부르는 것이죠. 그냥 문자일뿐이고, String[ ] 처럼 문자열 배열은 따로 있는데, 무슨말인가 복잡해 보일 것입니다. 단순히 생각하면 문자들이 모여있는 하나하나의 문자가 배열처럼 여러개가 있는 구조입니다. 아래 예를 살펴 보겠습니다.

package example;

public class StringEx4 {

	public static void main(String[] args) {
		
		String text = "Hello Hong Gil Dong";
		
		System.out.println("0번 인덱스 : "+text.charAt(0));
		
		for (int i=0; i<text.length(); i++) {
			System.out.println(text.charAt(i));
		}

	}

}

 

실행 결과

0번 인덱스 : H
H
e
l
l
o

H
o
n
g

G
i
l

D
o
n
g

 

text 변수에 "Hello Hong Gil Dong"이라는 문자열 값이 대입되었는데, 배열처럼 charAt() 메서드를 통해 0번 인덱스의 값 H가 출력되었다. 이 문자열을 for문을 이용해 text.length() 만큼 반복하면서 i변수를 인덱스로 활용해 출력도 할 수 있습니다.

 

여기서 실행 결과를 살펴 보면 Hello와 Hong 단어 사이의 o와 H 사이에 한줄의 공백이 보이는데, 이 공백도 하나의 문자열입니다. 문자열을 감싸는 기호 "" 사이에 아무값도 없으면 값이 없는게 아니라, 빈문자열이 됩니다. 보통 변수를 선언할 때, 초기값을 지정하지 않으면, 각 타입의 기본값으로 초기화되는데, String은 참조자료형이기 때문에 null로 초기화됩니다. 하지만 일반적으로 null 보다는 "" 빈 문자열로 초기화 해주는 형태를 많이 사용합니다.

 

package example;

public class StringEx5 {
	
	static String s1;
	static String s2 = "";

	public static void main(String[] args) {
		
		System.out.println(s1);
		System.out.println(s2);

	}

}

 

실행 결과

null

 

StringEx5 클래스의 static 변수 s1은 초기화 되지 않은 String 객체인데 실행 결과를보면 null이 출력되었습니다. 그런데 s2의 출력결과는 보이지 않는데, 값이 출력되지 않은 것이 아니라, 빈 문자열 ""이 출력된 것입니다.

package example;

public class StringEx6 {
	
	public static void main(String[] args) {
		
		String s1 = "";
		
		System.out.println("s1.length():"+s1.length());
		System.out.println("".equals(s1));

	}

}

 

실행 결과

s1.length():0
true

 

"" 빈 문자열의 길이는 0입니다. 길이가 없긴 하지만 값이 없는 것이 아니라 빈 값이 있는 것이기 때문에 "".equals(s1) 의 결과는 true가 됩니다.

 

 

3. String 메서드

이제, String 클래스에서 자주 사용하는 메서드들을 살펴보도록 하겠습니다. String 클래스는 모든 프로그램에서 사용하지 않는 경우가 없을 만큼 가장 많이 사용되는 클래스 중의 하나로 메서드의 종류와 사용법을 알아두면 편리합니다.

메서드 기능
chatAt(int index) 문자열의 index 위치의 문자 리턴
equals(Object obj) 해당 문자열의 값과 obj의 문자열 값을 비교
indexOf(String str) 문자열내 매개변수 문자열의 위치 리턴
indexOf(char ch) 문자열내 매개변수 문자(char)의 위치 리턴
substring(int start) 매개변수 start 위치(인덱스)에서 끝까지 잘라냄
substring(int start, int end) 매개변수 start위치 부터 end위치 전 인덱스까지 잘라냄
toLowerCase() 문자열을 소문자로 변환하여 리턴
toUpperCase() 문자열을 대문자로 변환하여 리턴
trim() 문자열의 앞과 뒤 공백을 제거하여 리턴(중간의 공백은 제거 안됨)
valueOf(기본자료형 i) 기본자료형 값을 문자열로 변환하여 리턴
length() 문자열의 길이를 리턴
startsWith(String str) 문자열 중 매개변수 str로 시작하면 true 그렇지 않으면 false 리턴
endsWith(String str) 문자열 중 매개변수 str로 끝나면 true 그렇지 않으면 false 리턴
replace(String old, String new) 문자열 중 oldnew로 치환
replaceAll(String regex, String replacement) 문자열 중 매개변수 문자열 regexreplacement로 치환 (정규식 사용 가능)
split(String regex) 문자열을 매개변수 regex를 구분자로 나눠서 배열로 리턴
toString() String 객체에 저장되어 있는 문자열 리턴

 

위 문자열 관련 메서드를 사용한 예제를 살펴보겠습니다.

package example;

public class StringEx7 {
	
	public static void main(String[] args) {
		
		String str = "Hello My Name is Hong Gil Dong";
		
		System.out.println(str.charAt(6)); // 6번 인덱스의 문자
		System.out.println(str.equals("Hello My Name is Hong Gil Dong")); // 문자열값 비교
		System.out.println(str.indexOf("Hong")); // "Hong" 문자열의 위치
		System.out.println(str.indexOf('H')); // 'H'문자의 위치
		System.out.println(str.substring(17)); // 17번 인덱스부터 끝까지 잘라냄
		System.out.println(str.substring(6, 13)); // 6번 인덱스부터 13전(12번 인덱스)까지 문자열
		System.out.println(str.toLowerCase()); // 소문자로 변경
		System.out.println(str.toUpperCase()); // 대문자로 변경
		System.out.println(str.length()); // 문자열의 길이
		System.out.println(str.startsWith("Hello")); // "Hello"으로 시작하는지 여부
		System.out.println(str.endsWith("Dong")); // "Dong"으로 끝나는지 여부
		System.out.println(str.replace("Hong", "Kim")); // "Hong"을 "Kim"으로 치환
		System.out.println(str.replaceAll("Name", "NickName")); // "Name"을 "NickName"으로 치환
		System.out.println(str.toString());
		
		str = "   안녕 하세요,     반갑습니다.      ";
		System.out.println(str.trim()); // 앞뒤 공백 제거
		// 모든 공백을 제거하는 방법
		System.out.println(str.replace(" ", ""));
		
		str = String.valueOf(10); // 기본자료형 int를 문자열로 변환
		str = String.valueOf(10.5); // 기본자료형 double을 문자열로 변환
		
		str = "홍길동,이순신,유관순,안중근";
		String[] arr = str.split(","); // ,를 구분자로 나눠서 배열로 리턴
		for (int i=0; i<arr.length; i++) {
			System.out.println(i+"번 인덱스 값 = "+arr[i]);
		}

	}

}

 

실행 결과

M 
true 
17 
0 
Hong Gil Dong 
My Name 
hello my name is hong gil dong 
HELLO MY NAME IS HONG GIL DONG 
30 
true 
true 
Hello My Name is Kim Gil Dong 
Hello My NickName is Hong Gil Dong 
Hello My Name is Hong Gil Dong 
안녕 하세요,     반갑습니다.
안녕하세요,반갑습니다.
0번 인덱스 값 = 홍길동 
1번 인덱스 값 = 이순신 
2번 인덱스 값 = 유관순 
3번 인덱스 값 = 안중근

 

 

기본자료형 값을 문자열로 변경하는 방법 중 편한 방법이 + 덧셈연산을 하는 방법과 valueOf() 메서드를 사용하는 방법이 있는데, 성능상으로는 valueOf()가 더 좋다고 하지만 큰 차이는 아니므로 편한 방법으로 사용하면 됩니다. 추가로 기본자료형 값들을 문자열로 변경하는 방법과 반대로 문자열을 기본자료형으로 변경하는 방법을 알아보겠습니다.

기본자료형 -> 문자열 문자열 -> 기본자료형
String.valueOf(boolean b)
String.valueOf(char c)
String.valueOf(int i)
String.valueOf(long l)
String.valueOf(float f)
String.valueOf(double d)
Boolean.getBoolean(String s)
Byte.parseByte(String s)
Short.parseShort(String s)
Integer.parseInt(String s)
Long.parseLong(String s)
Float.parseFloat(String s)
Double.parseDouble(String s)

 

기본자료형에서 문자열로 변환하는 방법은 String 클래스의 valueOf()메서드 하나를 사용하면 됩니다. 매개변수만 다르기 때문이죠.(오버로딩)

그리고 문자열을 기본자료형으로 변환하는 방법은 기본자료형 이름 그대로 첫자만 대문자로 된 클래스이름에 메서드는 parseXXX 이므로 하나하나 외우지 말고 메서드 이름 규칙을 기억하면 어렵지 않게 기억할 수 있을 것입니다.

package example;

public class StringEx8 {
	
	public static void main(String[] args) {
		
		String[] str = {"1", "2", "3", "4"};
		
		int sum1 = 0;
		for (int i=0; i<str.length; i++) {
			sum1 += Integer.parseInt(str[i]);
		}
		System.out.println("sum1 = "+sum1);
		
		long sum2 = 0;
		for (int i=0; i<str.length; i++) {
			sum2 += Long.parseLong(str[i]);
		}
		System.out.println("sum2 = "+sum2);
		
		double sum3 = 0;
		for (int i=0; i<str.length; i++) {
			sum3 += Double.parseDouble(str[i]);
		}
		System.out.println("sum3 = "+sum3);

	}

}

 

실행 결과

sum1 = 10
sum2 = 10
sum3 = 10.0

 

문자열 배열 변수 str"1", "2", "3", "4" 네 개의 문자열 값을 대입하고 int, long, double 자료형의 sum1, sum2, sum3 변수에 for문을 사용해 문자열 배열의 각 값들을 기본자료형으로 변환해 합계를 구해서 출력했습니다.