String 클래스

박영준·2023년 4월 14일
0

Java

목록 보기
66/111

1. 정의

  • 문자열 리터럴은 String 객체로 자동 생성되지만
    String 클래스를 이용하면, 다양한 생성자로 직접 String 객체를 생성할 수 있다.

  • char[] 와 메서드(기능)를 결합한 것

    • String 클래스는 char 배열에 기능을 추가해서 확장한 것.
      • String 클래스를 사용하는 편이 문자열을 다루기에 편리하기 때문
  • 문자열을 많이 사용하기 때문에 특별하게 만들어진 클래스

  • name = name + firstName;

    String name = "choi"; 와 String firstName = "wb"; 가 있을 경우,
    기존의 name 은 firstName과 합쳐져서 새로운 name이 된다. (기존의 name을 대체하게 됨)

  • String은 읽기만 가능. 수정은 불가능

    String str = "Java";
    str = str + "Good";
    
    System.out.println(str);		// JavaGood

2. String vs StringBuffer

String

String a = "가";
String b = "나";
a = a + b;		// a = "가나"
  • '+ 연산자'를 이용해서 문자열을 더할 경우,
    매 연산마다 새로운 문자열을 가진 Stirng 인스턴스가 생성되어, 메모리 공간을 차지하게 된다

    • 문자열을 다루는 작업 多수록, 효율적이지 않은 방법!
    • 이때 StringBuffer클래스(문자열의 변경이 가능)가 필요해진다
  • 추가만 됐을 뿐, 기존의 문자열에는 수정이 이뤄지지 않음

StringBuffer

3. 메소드

char charAt(int index)
해당 문자열의 특정 인덱스에 해당하는 문자를 반환함.

int compareTo(String str)
해당 문자열을 인수로 전달된 문자열과 사전 편찬 순으로 비교함.

int compareToIgnoreCase(String str)
해당 문자열을 인수로 전달된 문자열과 대소문자를 구분하지 않고 사전 편찬 순으로 비교함.

String concat(String str)
해당 문자열의 뒤에 인수로 전달된 문자열을 추가한 새로운 문자열을 반환함.

int indexOf(int ch), int indexOf(String str)
해당 문자열에서 특정 문자나 문자열이 처음으로 등장하는 위치의 인덱스를 반환함.

int indexOf(int ch, int fromIndex), int indexOf(String str, int fromIndex)
해당 문자열에서 특정 문자나 문자열이 전달된 인덱스 이후에 처음으로 등장하는 위치의 인덱스를 반환함.

int lastIndexOf(int ch)
해당 문자열에서 특정 문자가 마지막으로 등장하는 위치의 인덱스를 반환함.

int lastIndexOf(int ch, int fromIndex)
해당 문자열에서 특정 문자가 전달된 인덱스 이후에 마지막으로 등장하는 위치의 인덱스를 반환함.

String[] split(String regex)
해당 문자열을 전달된 정규 표현식(regular expression)에 따라 나눠서 반환함.

  • split(String regex) : 구분자를 바탕으로 배열 형식으로 문자열을 자른다
  • split(String regex, int limit) : 구분자를 바탕으로 배열 형식으로 문자열을 자르지만, limit 수만큼 자른다

String substring(int beginIndex)
해당 문자열의 전달된 인덱스부터 끝까지를 새로운 문자열로 반환함.

String substring(int begin, int end)
해당 문자열의 전달된 시작 인덱스부터 마지막 인덱스까지를 새로운 문자열로 반환함.
단, 마지막 end는 포함 X

String toLowerCase()
해당 문자열의 모든 문자를 소문자로 변환함.

String toUpperCase()
해당 문자열의 모든 문자를 대문자로 변환함.

String trim()
해당 문자열의 맨 앞과 맨 뒤에 포함된 모든 공백 문자를 제거함.

length()
해당 문자열의 길이를 반환함.

isEmpty()
해당 문자열의 길이가 0이면 true를 반환하고, 아니면 false를 반환함.

char[] toCharArray()
문자열을 문자배열(char[])로 변환해서 반환함.

repeat()
String 문자열을 파라미터의 주어진 횟수만큼 반복

join()

  • Java 8에서 추가된 메소드

  • 문자열을 결합하기 위한 메서드 (split 메서드의 반대라고 생각하면 됨)

    • String.join("추가할 문자", "대상 list")
    • String.join("추가할 문자", "대상 Array")

4. 변수 생성 방법

1) new 연산자

class Ex {
	public static void main(String args[]) {
    	String str3 = new String("example");
		String str4 = new String("example");
    }
}

  • Heap 영역에 존재

참고: new 연산자

2) 문자열 리터럴

class Ex {
	public static void main(String args[]) {
    	String str1 = "apple";
		String str2 = "apple";
    }
}

  • string constant pool 영역에 존재
    → 같은 메모리 주소를 갖는다.

  • 문자열 리터럴이 같은 내용이라면, 한 번만 저장된다.

    • str1, str2 참조변수는 모두 하나의 String 인스턴스를 참조한다

리터럴 방식의 장점?
String 의 특성상 리터럴 방식이 메모리 절약 차원에서 유리하다.

('new'로 선언했을 때와는 달리) String 이 리터럴 방식으로 선언되었을 때는
변수마다 각자 다른 개별 공간이 아닌, '스트링 상수 풀 String constant pool'이라는 공동 공간에 문자열이 저장된다..
(공동 공간에 저장된다면, 메모리 주소 또한 같은 메모리 주소를 갖는다는 것)

5. 배열의 생성

예시 1

String[] name = new String[3];
name[0] = new String("Kim");
name[1] = new String("Park");
name[2] = new String("Yi");

// new 연산자 없이도 생성은 가능하나, 위의 방식이 정석적인 방법
String[] name = new String[3];
name[0] = "Kim";
name[1] = "Park";
name[2] = "Yi";
  • 3개의 문자열을 담을 수 있는 배열을 생성
  • 참조형이기 때문에, 기본값 null 로 초기화

예시 2

String[] name = new String[] {"Kim", "Park", "Yi"}

예시 3

String[] name = {"Kim", "Park", "Yi"}

6. 사용법

예시 1 : byte[] → 문자열

byte[] 배열

// 배열 전체를 String 객체로 생성
String str = new String(byte[] bytes);

// 지정한 문자셋으로 디코딩
String str = new (byte[] bytes, String charsetName);

// 배열의 offset 인덱스 위치부터 length만큼 String 객체로 생성
String str = new (byte[] bytes, int offset, int length);

// 지정한 문자셋으로 디코딩
String str = new (byte[] bytes, int offset, int length, String charsetName);

byte[] → 문자열 변환

public class ByteToStringExample {
	public static void main(String[] args) {
    	byte[] bytes = {72, 101, 108, 108, 111, 32, 74, 97, 118, 97}
    
    	String str1 = new String(bytes);
        System.out.println(str1);
        
        String str2 = new String(bytes, 6, 4);		// 6 은 74 인덱스의 위치, 4 는 4개 를 뜻함
        System.out.println(str2);
	}
}

/* 실행 결과
Hello Java
Java */

예시 2 : 문자열 → byte[]

public class StringGetBytesExamplet {
	public static void main(String[] args) {
    	String str = "안녕하세요";

		// 기본 문자셋으로 인코딩 & 디코딩
     	byte[] bytesl = str.getBytes();
        System.out.println("bytes1.length: " + bytes1.length
        String str1 = new String(bytes1);
        System.out.println("bytes1->String: " + str1);

        try {

			// EUC-KR 을 이용해서, 인코딩 & 디코딩
			byte[] bytes2 = str.getBytes("EUC-KR");
			System.out.println("bytes2.length: " + bytes2.length);
			String str2 = new String(bytes2, "EUC-KR");
			System.out.println("bytes2->string: " + str2);

			// UTF-8 을 이용해서, 인코딩 & 디코딩
			byte[] bytes3 = str.getBytes("UTF-8");
			System.out.println("bytes3. length: " + bytes3.length);
			String str3 = new String(bytes3, "UTF-8");
			System.out.println("bytes3->string: " + str3);

		} catch (Unsupport tedEncodingException e) {
			e.printstackTrace();
		}
	}
}

/* 실행결과
bytes.length: 10
bytes1->String: 안녕하세요
gC토프")i0xebnt.iosicue I bytes2.length: 10
:(nofisso/)n| bytes2->string: 안녕하세요
bytes3.length: 15
bytes3->String: 안녕하세요 */

예시 3 : charAt() 문자 추출

문법

String str = "ABCDE";
char ch = str.charAt(3);		// D가 ch에 저장됨
  • 0, 1, 2, 3, 4 인덱스

방법 1 : String타입의 참조변수 뒤에 붙여서 사용

String str = new String();

char c = ' ';		// char타입의 변수 c를 선언
str = "안녕하세요";		// String타입의 참조변수 str에 "안녕하세요"라는 문자열을 저장

c = str.charAt(0);		// 변수 c에 str.charAt(0)의 값을 저장 → 'str이 가리키고 있는 문자열에서 0번째에 있는 문자를 char타입으로 변환한다.'

System.out.println(c);

/* 출력 결과
안 */

방법 2 : Scanner에서 next() 또는 nextLine() 뒤에 붙여서 사용

Scanner sc = new Scanner(System.in);

char c1 = ' ';
char c2 = ' ';

// String타입의 참조변수 뒤에 붙이지 않고, 입력받는 곳에 바로 붙여도 동일하게 사용 가능 → char타입의 변수 c1과 c2에 바로 저장
c1 = sc.next().charAt(0);
c2 = sc.nextLine().charAt(3);

System.out.println(c1);
System.out.println(c2);

sc.close();

예시 4 : equals() 문자열 비교

참고: ==, equals() - 2. equals()

예시 5 : indexOf() 문자열 찾기

public class StringIndexOfExample {
	public static void main(String[] args) {
    
    	String subject = "자바 프로그래밍";
        
        int location = subject.indexOf("프로그래밍");		// subject 참조변수에서 "프로그래밍" 문자열이 시작되는 인덱스를 리턴 
        System.out.println(location);		// 리턴값을 출력
        
        // "자바" 문자열을 포함하고 있지 않는 경우가 아니라면 (즉, "자바" 를 포함하고 있다면)
        if (subject.indexOf("자바") != -1) {		// 주어진 문자열이 포함되어 있지 않으면, -1 을 리턴하기 때문에 이런 식으로 표현했음
        	System.out.println("자바와 관련된 책이다.");
        } else {
        	System.out.println("자바와 관련없는 책이다.");
        }    
    }
}

/* 출력 결과
3
자바와 관련된 책이다. */

매개값으로 주어진 문자열이 시작되는 인덱스를 리턴
만약, 주어진 문자열이 포함되어 있지 않으면, -1 을 리턴

참고: 배열, ArrayList - ArrayList - (5) 값 검색

예시 6 : length() 문자열 길이

참고: 행렬의 덧셈

예시 7 : replace() 문자열 대치

1) replace()

예시 : 일반 문자열

public class StringReplaceExample {
	public static void main(String[] args) {
    	String oldstr = "자바는 객체 지향 언어입니다. 자바는 풍부한 API를 지원합니다.";
		String newstr = oldstr.replace("자바", "JAVA");
		System.out.println(oldstr);
		System. out.println(newstr);
	}
}

/* 실행 결과
자바는 객체 지향 언어입니다. 자바는 풍부한 API를 지원합니다.
JAVA는 객체 지향 언어입니다. JAVA는 풍부한 API를 지원합니다.
*/

예시 2 : 특수문자

public static void main(String[] args) {

	String old = "abh.cd";

    String.newchar = old.replaceAll(".", "z");		// 특수문자 . 이 z로 변환됨

    System.out.print(newchar);
}
/* 출력 결과
abhzcd */
  • replace(바꾸고 싶은 문자, 바꿀 문자)

  • 특수문자로 치환이 가능

2) replaceAll()

예시 1 : 특수문자

public static void main(String[] args) {

	String old = "abz.cd";

    String.newchar = old.replaceAll(".", "z");		// 모든 문자열이 z로 변환됨

    System.out.print(newchar);
}

/* 출력 결과
zzzzz */

예시 2 : 숫자

public static void main(String[] args) {

	String old = "05784362변환";

    String.newchar = old.replaceAll("[0-9]", "숫자");

    System.out.print(newchar);
}

/* 출력 결과
숫자숫자숫자숫자숫자숫자숫자숫자변환 */
  • replaceAll(바꾸고 싶은 문자, 바꿀 문자)

    • 단순히 문자열을 바꿀 때는 replace() 와 동일한 결과를 출력
  • 특수문자로 치환이 어렵다.

3) replaceFirst()

public static void main(String[] args) {

	String old = "abcad";
    
    String.newchar = old.replaceFirst("a", "z");
    
    System.out.print(newchar);
}

/* 출력 결과
zbcad */
  • replaceFirst(바꾸고 싶은 문자, 바꿀 문자)
    • 문자열 中 바꾸고 싶은 문자에 해당하는 문자가 다수 존재할 때, 처음으로 찾은 문자만 변환

예시 8 : substring() 문자열 잘라내기

참고: 가운데 글자 가져오기

예시 9 : toLowerCase(), toUpperCase() 알파벳 소·대문자 변경

// 예시 1
String original = "Java Programming";		// 원래의 original 변수에서 "Java Programming" 문자열이 변경된 것은 아님!
String lowerCase = original.toLowerCase();		// lowerCase 변수는 새로 생성된 "java programming" 문자열얼 참조
String upperCase = original.toUpperCase();		// upperCase 변수는 새로 생성된 "JAVA PRIGRAMMING" 문자열얼 참조

  • toLowerCase() : 모든 문자열을 소문자로 변환
    toUpperCase() : 모든 문자열을 대문자로 변환

  • 영어로 된 문자열을 대소문자와 관계없이 비교할 때 주로 사용

public class StringToLowerUpperCaseExample {
	public static void main(String[] args) {
    
    	String str1 "Java Programming";
    	String str2 = "JAVA Programming";
        
        System.out.println(str1.equals(str2);
        
        String lowerStr1 = str1.toLowerCase();
		String lowerStr2 = str2.toLowerCase();
        System.out.println(lowerStr1.equals(lowerStr2));
        
        // equalsIgnoreCase() 메소드를 사용하면, toLowerCase() & toUpperCase()로 대소문자 맞추고나서 equals()를 이용해야하는 번거로움 없어짐
        System.out.println(str1.equalsIgnoreCase(str2));
	}
}

/* 출력 결과
false
true
true */

예시 10 : trim() 문자열 앞뒤 공백 자르기

public class StringTrimExample {
	public static void main(String[] args) {
    	String tel1 = "  02";
        String tel2 = "123   ";
        String tel3 = "   1234   ";
        
		String tel = tel1.trim() + tel2.trim() + tel3. trim();
		System.out.println(tel);
	}
}

/* 실행 결과
021231234 */
  • 형변환 메서드(parseInt, parseFloat ...)는 문자열에 공백 또는 문자가 포함된 경우,
    예외(NumberFormatException)가 발생할 수 있으므로, trim()을 붙여주는 습관을 가지자.

예시 11 : valueOf() 문자열 변환

참고: Enum 클래스 (enumeration type, 열거체) - (2) valueOf() 메소드

예시 12 : split() 분리하기

1 : ,

String str = "Apple,Amazone,Google,Microsoft";
String[] list = str.split(",");

/* 실행 결과
[Apple, Amazon, Google, Microsoft]
*/
  • , 구분자를 넣었을 때 문자열을 배열로 분리

2 : 공백

String str = "Apple Amazon Google Microsoft";
String[] list = str.split(" ");

/* 실행 결과
[Apple, Amazon, Google, Microsoft]
*/

예시 13 : join() 결합하기

String animals = "dog, cat";
String[] arr = animals.split(",");
String arr = String.join("-", arr);

System.out.println(str);

/* 출력 결과
dog-cat
*/

7. 문제점

public class Main {
    public static void main(String[] args) {
        // 실험 1
        String str1 = "hello world";
        String str2 = str1.substring(5);

        System.out.println(str1);       // 실행 결과 : hello world
        System.out.println(str2);       // 실행 결과 :  world

        // 실험 2 : String 클래스의 문제점 1
        // 겉으로 보이는 모습
        String str3 = str1 + str2;      // "hello world" + " world"
        System.out.println(str3);       // 실행 결과 : hello world world

        // 실제 모습
        String str4 = new StringBuffer().append(str1).append(str2).toString();
        System.out.println(str4);       // 실행 결과 : hello world world

        // 실험 3 : String 클래스의 문제점 2
        String str5="";

        for (int i = 0; i < 10; i++) {
            str5 = str5 + "*";
        }

        System.out.println(str5);       // 실행 결과 : **********

        // 실험 4 : 해결법
        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < 10; i++) {
            sb.append("*");
        }

        String str6 = sb.toString();
        System.out.println(str6);
    }
}
  • 실험 2

    • 문자열과 문자열을 더할 경우, StringBuffer 객체를 만들고 append()메소드로 문자열을 누적 후, 다시 toString()메소드로 문자열 객체로 변환하는 과정을 거치게 됨
  • 실험 3

    • 반복에서 문자열이 더해질 때마다, 매 반복횟수에서 StringBuffer 객체를 만든다.(10번 반복이면 10번 만듦)
      이는 속도를 저하시킨다.
  • 실험 4

    • 직접 StringBuffer 객체를 만들고, StringBuffer의 메소드를 통해 반복문을 수행하도록 한다.

참고: String 클래스
참고: [자바 프로그래밍 기초] 4. charAt()에 대해서 알아보자.
참고: 자바 특정 문자 & 특수 문자 제거/치환하기 (replace, replaceAll, replaceFirst)함수 사용
참고: 완벽정리! 자바 string 문자열을 배열로 분리하기

profile
개발자로 거듭나기!

0개의 댓글