자바의 기초 - 자료형 - 문자열

반응형

문자열

문자열이란 다음처럼 문자로 구성된 문장을 뜻한다.

"Happy Java"  
"a"  
"123"

자바에서 문자열을 나타내는 자료형은 String이다. 앞의 문자열을 자바에서 표현해 보자.

String a = "Happy Java";  // 문자열의 앞과 뒤는 쌍따옴표("")로 감싸야 한다.
String b = "a";
String c = "123";

다음과 같이 표현할 수도 있다.

String a = new String("Happy Java");
String b = new String("a");
String c = new String("123");

 

이때 new 키워드는 객체를 만들 때 사용한다. 문자열을 표현할 때는 가급적이면 첫 번째 방식, 즉 리터럴(literal) 표기 방식을 사용하는 것이 좋다. 왜냐하면 리터럴 표기 방식은 가독성이 좋고 컴파일할 때 최적화에 도움을 주기 때문이다.

 

점프 투 자바리터럴 표기 방식 이해하기

 

String a = "Happy Java"  String b = new String("Happy Java")에서 a, b 변수는 같은 문자열 값을 갖게 되지만 완전히 동일하지는 않다. 첫 번째 코드는 리터럴(literal) 표기 방식이라고 하는데 고정된 값을 그대로 대입하는 방법을 말한다. 이와 달리 두 번째 방식은 항상 새로운 String 객체를 만든다.

첫 번째 방식은 동일한 리터럴을 사용할 경우 새로운 String 객체를 만들지 않고 기존에 만든 것을 재활용한다.

원시 자료형

앞에서 살펴보았던 int, long, double, float, boolean, char 자료형을 원시(primitive) 자료형이라고 한다. 이런 원시 자료형은 new 키워드로 값을 생성할 수 없다. 원시 자료형은 다음 리터럴 표기 방식으로만 값을 세팅할 수 있다.

boolean result = true;
char a = 'A';
int i = 100000;

 

여기서 반드시 기억해 둘 게 하나 있다. String은 리터럴 표기 방식을 사용할 수 있지만 원시 자료형에 포함되지 않는다. String은 리터럴 표기 방식을 사용할 수 있도록 자바에서 특별 대우해 주는 자료형이다.

점프 투 자바Wrapper 클래스

int, long, double, float, boolean, char 등의 원시 자료형에는 각각 그에 대응하는 Wrapper 클래스가 있다.

원시 자료형Wrapper 클래스

int Integer
long Long
double Double
float Float
boolean Boolean
char Character

멀티 스레드 환경에서 동기화를 지원하려면 원시 자료형대신 Wrapper 클래스를 사용해야 한다.

문자열 내장 메서드

String 자료형의 내장 메서드 중에서 자주 사용하는 것을 알아보자. String 자료형의 내장 메서드는 문자열 객체에 속한 함수라 할 수 있다. 문자열 합치기, 분할, 대소문자 변환 등의 문자열을 다양하게 활용할 수 있도록 도와주는 역할을 한다.

equals

equals 메서드는 문자열 2개가 같은지를 비교하여 결괏값을 리턴한다.

‘리턴한다’라는 것은 메서드에서 값을 반환하는 작업을 한다는 뜻이다. 메서드는 특정 작업을 수행한 후 결과를 호출한 곳으로 돌려주기 위해 리턴한다.

String a = "hello";
String b = "java";
String c = "hello";
System.out.println(a.equals(b)); // false 출력
System.out.println(a.equals(c)); // true 출력
false
true

문자열 a와 문자열 b에는 hello와 java가 각각 저장되어 있으므로 값이 서로 같지 않다. 따라서 equals 메서드를 호출하면 false를 리턴한다. 그러나 문자열 a와 문자열 c는 hello와 hello로 값이 서로 같으므로 true를 리턴한다.

이처럼 문자열의 값을 비교할 때는 반드시 equals를 사용해야 한다. 만약 equals 대신 == 연산자를 사용한다면 다음과 같은 결과가 발생한다.

String a = "hello";
String b = new String("hello");
System.out.println(a.equals(b));  // true
System.out.println(a == b);  // false
true
false

 

문자열 a와 b는 모두 hello로 값이 같지만 equals를 호출하면 true를, == 연산자를 사용하면 false를 리턴한다. a와 b는 값은 같지만 서로 다른 객체이기 때문이다. ==은 2개의 자료형이 같은 객체인지를 판별할 때 사용하는 연산자이므로 false를 리턴한다.

indexOf

indexOf는 문자열에서 특정 문자열이 시작되는 위치(인덱스값)를 리턴한다. 문자열 a에서 Java가 시작되는 위치를 알고 싶다면 indexOf를 사용하여 다음처럼 위치를 리턴받을 수 있다.

String a = "Hello Java";
System.out.println(a.indexOf("Java"));  // 6 출력
6

문자열 Hello Java에서 특정 문자열인 Java는 일곱 번째 문자인 J부터 시작된다. 이때 결괏값이 7이 아닌 6으로 나온 이유는 자바에서는 숫자를 0부터 세기 때문이다.

contains

contains 메서드는 문자열에서 특정 문자열이 포함되어 있는지 여부를 리턴한다.

String a = "Hello Java";
System.out.println(a.contains("Java"));  // true 출력
true

문자열 a는 Java라는 문자열을 포함하고 있어서 true를 리턴한다.

charAt

charAt 메서드는 문자열에서 특정 위치의 문자를 리턴한다. Hello Java 문자열에서 J는 여섯번째 인덱스에 위치한 문자이다. 인덱스 6으로 문자 J를 리턴받으려면 다음과 같이 charAt을 사용한다.

String a = "Hello Java";
System.out.println(a.charAt(6));  // "J" 출력
J

replaceAll

replaceAll 메서드는 문자열에서 특정 문자열을 다른 문자열로 바꿀 때 사용한다. 다음 예에서는 Hello Java 문자열에서 Java를 World로 바꾸었다.

String a = "Hello Java";
System.out.println(a.replaceAll("Java", "World"));  // Hello World 출력
Hello World

substring

substring 메서드는 문자열에서 특정 문자열을 뽑아낼 때 사용한다.

String a = "Hello Java";
System.out.println(a.substring(0, 4));  // Hell 출력
Hell

 

위처럼 substring(시작 위치, 끝 위치)와 같이 코드를 작성하면 문자열의 시작 위치에서 끝 위치까지의 문자를 뽑아내게 된다. 단, 끝 위치의 문자는 포함이 안 된다는 점에 주의하자. 이것은 다음과 같은 수학의 식과 비슷하다.

시작위치 <= a < 끝위치

toUpperCase

toUpperCase 메서드는 문자열을 모두 대문자로 변경할 때 사용한다.

String a = "Hello Java";
System.out.println(a.toUpperCase());  // HELLO JAVA 출력
HELLO JAVA

문자열을 모두 소문자로 변경할 때는 toLowerCase를 사용한다.

split

split 메서드는 문자열을 특정한 구분자로 나누어 문자열 배열로 리턴한다.

String a = "a:b:c:d";
String[] result = a.split(":");  // result는 {"a", "b", "c", "d"}

이번 예처럼 a:b:c:d라는 문자열을 :(콜론)으로 나누어 {"a", "b", "c", "d"} 문자열 배열을 만들 수 있다.

문자열 포매팅

문자열에서 또 하나 알아야 할 것으로 문자열 포매팅(formatting)이 있다. 먼저, 다음 문자열을 출력하는 프로그램을 작성했다고 가정해 보자.

"현재 온도는 18도입니다."

시간이 지나서 20도가 되면 다음 문자열을 출력한다.

"현재 온도는 20도입니다."

 

위 두 문자열은 각각 18과 20이라는 숫자만 다를 뿐 형식은 같다. 이렇게 문자열 안의 특정한 값을 바꿀 수 있게 해주는 것이 바로 문자열 포매팅 기법이다. 문자열 포매팅이란 쉽게 말해 문자열 안에 어떤 값을 삽입하는 방법이다. 다음 예를 직접 실행해 보면서 문자열 포매팅 기법을 알아보자.

숫자 바로 대입하기

문자열 포매팅은 String.format 메서드를 사용한다.

System.out.println(String.format("I eat %d apples.", 3));  // "I eat 3 apples." 출력
I eat 3 apples.

 

이 예제의 결괏값을 보면 알겠지만, 문자열 안에 정수 3을 삽입하는 방법을 보여 준다. 문자열 안에서 숫자를 넣고 싶은 자리에 %d를 입력하고, 삽입할 숫자 3을 두 번째 파라미터로 전달했다. %d는 문자열 포맷 코드라고 한다. 문자열 포맷 코드는 잠시 뒤에 더 자세히 다룬다. 여기서는 이런 것이 있다는 것만 알자.

문자열 바로 대입하기

문자열 안에 꼭 숫자만 넣으라는 법은 없다. 이번에는 숫자 대신 문자열을 넣어 보자.

System.out.println(String.format("I eat %s apples.", "five"));  // "I eat five apples." 출력
I eat five apples.

 

이 예제에서는 문자열 안에 또 다른 문자열을 삽입하기 위해 앞에서 사용한 문자열 포맷 코드 %d가 아니라 %s를 썼다. 눈치 빠른 사람은 벌써 유추했을 것이다. 숫자를 넣기 위해서는 %d를, 문자열을 넣으려면 %s를 써야 한다는 사실을 말이다.

숫잣값을 나타내는 변수 대입하기

다음 예를 살펴보자.

int number = 3;
System.out.println(String.format("I eat %d apples.", number));  // "I eat 3 apples." 출력
I eat 3 apples.

 

숫자를 바로 대입하는 방법과 결과는 같지만, 이 예제는 숫잣값을 나타내는 변수를 대입한다.

값을 2개 이상 넣기

그렇다면 문자열 안에 값을 여러 개 넣으려면 어떻게 하는지 알아보자. 다음처럼 값을 2개 이상 넣으려면 파라미터를 순서대로 전달하면 된다.

int number = 10;
String day = "three";
System.out.println(String.format("I ate %d apples. so I was sick for %s days.", number, day));
I ate 10 apples. so I was sick for three days.

문자열 포맷 코드

문자열 포맷 코드의 종류

지금까지 문자열 포매팅 예제에서는 대입해 넣는 자료형으로 정수와 문자열을 사용했는데 이 외에도 다양한 종류가 있다. 문자열 포맷 코드의 종류를 알아보자.

코드설명

%s 문자열(String)
%c 문자 1개(character)
%d 정수(Integer)
%f 부동소수(floating-point)
%o 8진수
%x 16진수
%% Literal % (문자 % 자체)

 

여기에서 재미있는 것은 %s 포맷 코드인데, 이 코드는 어떤 형태의 값이든 변환해 넣을 수 있다.

다음 예를 통해 %s 포맷 코드를 확인해 보자.

System.out.println(String.format("I have %s apples",  3));  // "I have 3 apples" 출력
System.out.println(String.format("rate is %s", 3.234));  // "rate is 3.234" 출력
I have 3 apples
rate is 3.234

 

문자열 안에 3을 삽입하려면 %d, 3.234를 삽입하려면 %f를 사용해야 한다. 하지만 %s를 사용하면 이런 것을 생각하지 않아도 된다. 왜냐하면 %s는 자동으로 전달되는 파라미터 값을 문자열로 바꾸어 사용하기 때문이다.

점프 투 자바문자열 포맷 코드 %%의 쓰임

System.out.println(String.format("Error is %d%.", 98));
Exception in thread "main" java.util.UnknownFormatConversionException: Conversion = '.'
(... 생략 ...)

 

이 예제의 결괏값은 당연히 Error is 98%.가 출력될 것이라고 예상하겠지만 ‘UnknownFormatConversionException’이라는 오류가 발생한다.

문자열 포맷 코드인 %d와 %가 같은 문자열 안에 있을 때 특수 문자인 %를 나타내려면 반드시 %%로 써야 하기 때문이다. 하지만 문자열 안에 %d 같은 포맷 코드가 없으면 특수 문자 %는 홀로 쓰여도 상관이 없다. 따라서 원하는 결괏값을 얻으려면 코드를 수정해야 한다. 수정한 코드를 살펴보자.

System.out.println(String.format("Error is %d%%.", 98));  // "Error is 98%." 출력
Error is 98%.

문자열 포맷 코드 응용하기

앞서 보았듯이 %d, %s 등은 문자열 안에 어떤 값을 삽입할 때 사용한다. 포맷 코드는 숫자와 함께 사용하면 더 유용하다.

1. 정렬과 공백 표현하기

다음 예를 살펴보자.

System.out.println(String.format("%10s", "hi"));  // "        hi" 출력
        hi

이 예제에서 %10s는 전체 길이가 10인 문자열 공간에서 대입되는 값(hi)을 가장 오른쪽으로 정렬하고 나머지는 공백으로 남겨 두라는 의미이다.

 

그렇다면 왼쪽 정렬은 %-10s을 입력하면 되지 않을까? 한번 확인해 보자.

System.out.println(String.format("%-10sjane.", "hi"));  // "hi        jane." 출력
hi        jane.

이번에는 hi를 왼쪽으로 정렬하고 나머지는 공백과 jane으로 채웠음을 알 수 있다.

 

2. 소수점 표현하기

다음 예를 살펴보자.

System.out.println(String.format("%.4f", 3.42134234));  // 3.4213 출력
3.4213

%.4f는 3.42134234를 소수점 넷째 자리까지만 나타내고 싶을 때 사용한다. 문자열 포맷 코드에서 ‘.’는 소수점을 뜻하고, 그 뒤의 숫자 4는 소수점 뒤에 이어질 숫자의 개수를 말한다.

 

이번엔 좀 더 나아가 숫자 3.42134234를 소수점 넷째 자리까지 표시하고 전체 길이가 10인 문자열 공간에서 오른쪽 정렬한 소수를 출력해 보자.

System.out.println(String.format("%10.4f", 3.42134234));  // '    3.4213' 출력
    3.4213

System.out.printf

String.format 메서드는 포매팅된 문자열을 리턴한다. 따라서 앞선 예제에서 포매팅된 문자열을 출력할 때 System.out.println 메서드를 함께 사용했다.

System.out.println(String.format("I eat %d apples.", 3));

 

하지만 System.out.printf 메서드를 사용하면 String.format 메서드가 없어도 같은 형식으로 간단히 포매팅된 문자열을 출력할 수 있다.

System.out.printf("I eat %d apples.", 3);  // "I eat 3 apples." 출력
I eat 3 apples.

 

String.format은 문자열을 리턴하는 메서드이고, System.out.printf는 문자열을 출력하는 메서드라는 점에서 차이가 있다. 상황에 맞게 선택하여 사용하자.

반응형