본문 바로가기
Java의 정석/java.lang 패키지 & 유용한 클래스

String 클래스, 문자열 비교, 빈 문자열

by Hwanii_ 2023. 8. 31.
728x90
ch9 - 7 ~ 10

String 클래스, 문자열 비교, 빈 문자열

 

ch9-7 String 클래스

문자열을 다루기 위한 클래스 이다.

- String 클래스 = 데이터 (char[]) + 메서드 (문자열 관련)

(멤버변수로 char[] 을 가진다. (문자 배열) )

- 내용을 변경할 수 없는 불변 (immutable) 클래스.

ex)

String a = "a";
String b = "b";

a = a + b;

>> "ab" (문자열 결합)

a --- 0x100

b --- 0x200

ab --- 0x300

결합된 문자열 "ab" 는 새롭게 new 된 아이이고, 얘를 변수 a에 대입 하는 개념.

- 덧셈 연산자 (+) 를 이용한 문자열 결합은 성능이 떨어 진다.
(계속 새로운 객체를 생성 하는 개념이니까)

따라서, 문자열의 결합이나 변경이 잦다면, 내용을 변경 가능한 StringBuffer를 사용 한다.
(내용 변경 가능)

 

ch9-8 문자열의 비교

- String str = "abc"; 와 String str = new String("abc"); 의 비교.

String str1 = "abc";    //  문자열 리터럴 "abc" 의 주소가 str1에 저장 된다.
String str2 = "abc";    //  문자열 리터럴 "abc" 의 주소가 str2에 저장 된다.

리터럴 이란 ?
변수에 입력되는 값을 의미 한다.

String str3 = new String("abc");    //  새로운 String 인스턴스를 생성.
String str4 = new String("abc");    //  새로운 String 인스턴스를 생성.

str1 --- 0x100 ---> "abc" (0x100)
str2 --- 0x100 ---> "abc" (0x100)

str3 --- 0x200 ---> "abc" (0x200)
str4 --- 0x300 ---> "abc" (0x300)

str1 == str2
0x100 == 0x100
true

str3 == str4
0x200 == 0x300
false

어차피 문자열은 불변의 법칙을 가져서, 내용 변경이 불가능 하기 때문에,
객체 자체를 여러개 만들 필요가 없다.
따라서, new 하지 않는다.

그리고, "문자열" 을 비교 할 때는 등가 비교 연산자를 ( == ) 사용 하지 않는다.
왜냐하면, 등가 비교 연산자는 "주소값"을 비교 하기 때문 이다.
따라서, 문자열 비교시는 항상 equals() 메서드를 사용해서 "내용"을 비교 해야 한다.

 

문자열 리터럴인 "abc" 는 프로그램 실행시 자동으로 생성 된다.

(아래에서 자세히 다룸)

 

같은 내용의 문자열 리터럴은 하나만 만들어지기 때문에,

동일한 내용의 문자열 리터럴은 같은 주소값을 가지게 된다.

 

따라서, "abc" 문자열 리터럴의 주소값이 0x100 이라고 가정하면,

그 주소값을 참조변수 str1과 참조변수 str2에 대입하고,

이 둘은 같은 주소값을 가지게 된다.

 

그래서,

이 둘은,

== 를 사용해도 true가 나오게 되고,

.equals() 메서드를 사용해도 true가 나오게 된다.

 

예시 )

 

class Ex9_6 {

    public static void main(String[] args) {

        String str1 = "abc";
        String str2 = "abc";

        System.out.println("String str1 = \"abc\";");
        System.out.println("String str2 = \"abc\";");

        System.out.println("str1 == str2 ?  " + (str1 == str2));
        System.out.println("str1.equals(str2) ? " + str1.equals(str2));
        System.out.println();

        String str3 = new String("abc");
        String str4 = new String("abc");

        System.out.println("String str3 = new String(\"abc\");");
        System.out.println("String str4 = new String(\"abc\");");

        System.out.println("str3 == str4 ? " + (str3 == str4));
        System.out.println("str3.equals(str4) ? " + str3.equals(str4));
    }
}

 

[ console ]

 

 

참조변수 str3과 str4는 new를 해서 새로운 인스턴스를 생성 했다.

 

이 둘은 서로 다른 객체 이다.

즉, 다른 주소값을 가지기 때문에,

등가 비교 연산자로 비교를 하면 결과값은 false 가 나오게 된다.

생성자의 인자로 "abc" 를 넣었기 때문에,

값을 비교 하고 싶으면, equals() 메서드를 사용 한다.

 

ch9-9 문자열 리터럴

- 문자열 리터럴은 프로그램 실행시 자동으로 생성 된다.
(constant pool (상수 저장소) 에 저장)

프로그램에 있는 모든 문자열은 원래대로 라면 String 클래스 이기 때문에,
객체 생성 (new) 를 해야 하는데,
문자열에 대해서만, 프로그램 실행시 constant pool에 자동으로 생성 된다.

- 같은 내용의 문자열 리터럴은 하나만 만들어진다.

str1 --- 0x100 ---> "AAA" (0x100)
str2 --- 0x100 ---> "AAA" (0x100)
str3 --- 0x100 ---> "AAA" (0x100)

 

문자열 리터럴 "AAA"가 0x100 라는 주소값을 가진다고 가정 하면,

모든 "AAA" 리터럴은 같은 주소값을 가지기 때문에,

참조변수 str1, str2, str3 은 같은 주소값을 가리키는 참조변수가 된다.

 

constant pool 이란 ?

JVM 내에서 사용되는 메모리 영역 중 하나 이다.
주로 리터럴 값과 상수 값을 저장 한다.

클래스 파일 내에 저장된 상수들을 관리하고, 클래스 파일을 로드할 때마다 JVM 메모리에 로드 된다.

즉,
자바에서 선언한 상수 또는 문자열 리터럴 등은,
컴파일 시에 클래스 파일에 constant pool 에 저장되고,
이렇게 저장된 상수들은 런타임 중에 필요 할 때,
해당 클래스로부터 constant pool 을 참조해서 사용 된다.

 

ch9-10 빈 문자열 ("", empty string)

- 내용이 없는 문자열. 크기가 0인 char형 배열을 저장하는 문자열.

String str = "";    //  str을 빈 문자열로 초기화.

- 크기가 0인 배열을 생성 하는 것은 어느 타입이나 가능.

char[] chArr = new char[0]; //  길이가 0인 char 배열.

int[] iArr = {};    //  길이가 0인 int 배열.

몇 바이트를 차지하는지가 배열의 크기 이다.

예를들어 int 타입의 배열 이면,
배열의 한 요소가 4바이트를 차지하고,
길이가 10이면, 총 40바이트 이다.

- 문자 (char) 와 문자열 (String) 의 초기화

String s = "";  //  빈 문자열로 초기화.
char c = '';    //  공백으로 초기화.

위와 같이 한다.

그리고,

String s = null;
char c = '\u0000';

이렇게 하지는 않는다.
(\u0000 는 첫번째 문자를 뜻하는 유니코드)

 

예제 )

 

class Ex9_8 {

    public static void main(String[] args) {

        // 길이가 0인 char배열을 생성한다.
        char[] cArr = new char[0];    // char[] cArr = {};와 같다.

        String s = new String(cArr);  // String s = new String("");와 같다.

        System.out.println("cArr.length = " + cArr.length);
        System.out.println("@@@" + s + "@@@");
    }
}

 

[ console ]

 

 

char 배열의 길이는 0으로 생성 했기 때문에,

길이를 println() 하면 0이 나오는 것을 볼 수 있고,

 

char[] cArr = new char[0]; 은 char[] cArr = {};와 같다.

 

즉, 빈값을 의미 한다.

 

따라서,

참조변수 cArr을 String 인스턴스의 생성자의 인자에 넣으면,

결국 빈값인 " " 을 넣는것과 동일 하고,

이는, 문자열 " " == 빈 문자열 == 빈 값 을 의미 하게 된다.

 

결국 @@@ + " " + @@@ 의 결과는 @@@@@@ 이 된다.

 

ch9 - 11

String 클래스의 생성자와 메서드

ch9-11 String 클래스의 생성자와 메서드

 

자주 사용 하는 메서드가 있고, 자주 사용 하지 않는 메서드가 있다.

 

아래에 예시와 결과를 작성해놓은게 대다수지만,

그렇지 않은것들은 추후 추가 또는 구글 검색으로 해결 하기.

 

----------------------------------------------------------------------

String(String s) : 주어진 문자열 (s) 을 갖는 String 인스턴스를 생성. (생성자)
(잘 안쓴다)

예시 >>
String s = new String("Hello");

결과 >>
s = "Hello"

----------------------------------------------------------------------

String(char[] value) : 주어진 문자열 (value)을 갖는 String 인스턴스를 생성.

예시 >>
char[] c = {'H','e','l','l','o'};
String s = new String(c);

결과 >> s = "Hello"

----------------------------------------------------------------------

String(StringBuffer buf) :
StringBuffer 인스턴스가 갖고 있는 문자열과 같은 내용의 String 인스턴스를 생성.

----------------------------------------------------------------------

char charAt(int index) : 지정된 위치 (index) 에 있는 문자 1개를 반환.
(index는 0 부터 시작)

예시 >>
String s = "Hello";
String n = "0123456";
char c = s.charAt(1);
char c2 = n.charAt(1);

결과 >>
c = 'e'
c2 = '1'

----------------------------------------------------------------------

int compareTo(String str) :
문자열 (str) 과 사전 순서로 비교 한다. (사전 == Dictionary)
같으면 0,
사전순으로 이전이면 음수,
사전순으로 이후이면 양수를 반환.

예시 >>
int i = "aaa".compareTo("aaa");
int i2 = "aaa".compareTo("bbb");
int i3 = "bbb".compareTo("aaa");

결과 >>
i = 0
i2 = -1
i3 = 1

----------------------------------------------------------------------

 

----------------------------------------------------------------------

String concat(String str) :
문자열(str)을 뒤에 덧붙인다.

예시 >>
String s = "Hello";
String s2 = s.concat(" World");

결과 >>
s2 = "Hello world"

----------------------------------------------------------------------

boolean contains(CharSequence s) :
지정된 문자열(s) 이 포함 되었는지 검사.

예시 >>
String s = "abcedfg";
boolean b = s.contains("bc");

결과 >>
b = true

----------------------------------------------------------------------

boolean endsWith(String suffix) :
지정된 문자열 (suffix) 로 끝나는지 검사.

예시 >>
String file = "Hello.txt";
boolean b = file.endsWith("txt");

결과 >>
b = true

----------------------------------------------------------------------

boolean equals(0bject obj) :
매개변수로 받은 문자열 (obj)과 String 인스턴스의 문자열을 비교.
obj가 String이 아니거나 문자열이 다르면 false를 반환.

예시 >>
String s = "Hello";
boolean b = s.equals("Hello");
boolean b2 = s.equals("hello");

결과 >>
b = true
b2 = false

----------------------------------------------------------------------

boolean equalsIgnoreCase(String str) :
문자열과 String 인스턴스의 문자열을 대소문자 구분 없이 비교.

예시 >>
String s = "Hello";
boolean b = s.equalsIgnoreCase("HELLO");
boolean b2 = s.equalsIgnoreCase("hello");

결과 >>
b = true
b2 = true

----------------------------------------------------------------------

 

----------------------------------------------------------------------

int indexOf(int ch) :
주어진 문자 (ch) 가 문자열에 존재하는지 확인 하여 위치 (index) 를 반환.
못 찾으면 -1을 반환.
(index 는 0 부터 시작)

예시 >>
String s = "Hello";
int idx1 = s.indexOf('o');
int idx2 = s.indexOf('k');

결과 >>
idx1 = 4
idx2 = -1

----------------------------------------------------------------------

int indexOf(int ch, int pos) :
주어진 문자 (ch)가 문자열에 존재하는지 지정된 위치 (pos) 부터
확인하여 위치 (index) 를 알려 준다.
못 찾으면 -1 을 반환.
(index 는 0 부터 시작)

예시 >>
String s = "Hello";
int idx1 = s.indexOf('e', 0);
int idx2 = s.indexOf('e', 2);

결과 >>
idx1 = 1
idx2 = -1

----------------------------------------------------------------------

int lastIndexOf(int ch) :
지정된 문자 또는 문자 코드를 문자열의 오른쪽 끝에서 부터 찾아서 위치 (index) 를 알려 준다.
못 찾으면 -1 을 반환.

----------------------------------------------------------------------

int lastIndexOf(String str) :
지정된 문자열을 인스턴스의 문자열 끝에서 부터 찾아서 위치 (index) 를 알려 준다.
못 찾으면 -1 을 반환.

----------------------------------------------------------------------

int length() :
문자열의 길이를 알려 준다.

예시 >>
String s = "Hello";
int length = s.length();

결과 >>
length = 5

----------------------------------------------------------------------

 

----------------------------------------------------------------------

String[] split(String regex) :
정규식 : Regular Expression

문자열을 지정된 분리자 (regex) 로 나누어 문자열 배열에 담아 반환.

----------------------------------------------------------------------

String[] split(String regex, int limit) :
문자열을 지정된 분리자 (regex) 로 나누어 문자열 배열에 담아 반환.
단, 문자열 전체를 지정된 수 (limit) 로 자른다.

----------------------------------------------------------------------

boolean startsWith(String prefix) :
주어진 문자열 (prefix) 로 시작하는지 검사.

----------------------------------------------------------------------

String substring(int begin) :
String substring(int begin, int end) :

주어진 시작 위치 (begin) 부터 끝 위치 (end) 범위에 포함된 문자열을 얻는다.
이때,
시작 위치의 문자는 범위에 포함되지만,
끝 위치의 문자는 포함 되지 않는다.

(begin <= x < end)

----------------------------------------------------------------------

String toLowerCase() :
String 인스턴스에 저장 되어 있는 모든 문자열을 소문자로 변환 하여 반환.

----------------------------------------------------------------------

 

----------------------------------------------------------------------

String toUpperCase() :
String 인스턴스에 저장 되어 있는 모든 문자열을 대문자로 변환 하여 반환.

----------------------------------------------------------------------

String trim() :
문자열의 왼쪽 끝과 오른쪽 끝에 있는 공백을 없앤 결과를 반환.
이때, 문자열 중간에 있는 공백은 제거 되지 않는다.

----------------------------------------------------------------------

static String valueOf(boolean b)
static String valueOf(char c)
static String valueOf(int i)
static String valueOf(long l)
static String valueOf(float f)
static String valueOf(double d)
static String valueOf(Object o)

지정된 값을 문자열로 변환 하여 반환.
참조 변수의 경우, toString() 을 호출한 결과를 반환.

예시 >>
String b = String.valueOf(true);
String c = String.valueOf('a');
String i = String.valueOf(100);
String l = String.valueOf(100L);
String f = String.valueOf(10f);
String d = String.valueOf(10.0);

java.util.Date dd = new java.util.Date();
String date = String.valueOf(dd);

결과 >>
b = "true"
c = "a"
i = "100"
l = "100"
f =  "10.0"
d = "10.0"

date = "Wed Jan 27 21:26:29 KST 2016"

----------------------------------------------------------------------

 

반응형