본문 바로가기

프로그래밍/자바

[자바/기본] String 클래스/ StringBuilder / StringBuffer / StringTokenizer

728x90
반응형
SMALL

String이란?

  • 문자열이라고 불리는 클래스이다
  • 문자열이란 char형 변수가 이어진 형태 (char[]), 따라서 String은 기본 자료형이 아닌 클래스 이다.

 

String의 특징

  • 불변성 (immutable) && 공유성 : 자바에서 String은 불변 즉, 변하지 않는다. 처음 만들어지는 String의 값은 저장이 되어있고, 그 값에 변경을 줄 때, 새로운 값으로 저장이 되고 그 값을 가르키게 된다 (불변성).  또한, 변경을 준 값이 이미 메모리에 저장되어있을 때, 그 값의 주소값을 가르키게 된다(공유성).
public class Main {
    public static void main(String[] args){
        String str1 = "Hey";        // Hey라는 값이 저장
        System.out.println(str1);   //hey

        String str2 = "Hey";        //먼저 저장된 Hey라는 값을 가르키된다.
        System.out.println(str1 == str2);   //true

        str1 = str1+"12";           //Hey12 라는 값이 새롭게 저장되어 str1은 그 값을 가르킴
        System.out.println(str1);   //Hey12
        
        String str3 = "Hey12";
        str1 = "Hey".concat("12");  //concat 함수를 통한 String값 변경
        System.out.println(str1 == str3);   //false
    }
}
  • 위 예시를 보면 str1과 str2가 "Hey" 라는 값을 가르키게 되면서 true를 반환 하는 것을 볼수 있다.
  • 그렇다면 여기서 "같은 Hey 라는 값을 가지고 있으니까 true가 뜬거 아님?" 이라는 생각을 가질 수 있는데 응 아님
  • concat의 경우 새로운 배열을 리턴해주기 때문에 이미 Hey12 라는 값이 메모리에 있어도 새로운 Hey12 값을 메모리에 저장해서 그 값을 가르키게 됨으로 결과는 false가 나온다. 추가적인 설명은 밑에
public class Main {
    public static void main(String[] args){
        String str1 = new String("Hey");
        String str2 = new String("Hey");
        System.out.println(str1 == str2);       //false
        System.out.println(str1.equals(str2)); 	// true
    }
}
  • 위 코드를 보면 String의 생성자를 사용해서 Hey라는 값을 가진 String 을 두번 생성해주었다.
  • 따라서, str1과 str2 는 같은 Hey라는 값을 가진 String 객체
  • 하지만 str1 == str2 가 false가 나왔다는 것은 String의 비교는 주소값으로 이루어진다로 해석할 수 있다.
  • 따라서 String 객체의 값은 equals 함수를 통해서 비교할 수 있다.

StringBuffer / StringBuilder 란?

  • StringBuffer 와 StringBuilder 는 String 클래스와 달리 가변 (mutable) 클래스이다. 
  • StringBuffer경우 Java 버전 1부터 있었던 클래스, StringBuilder는 Java 5부터 생긴 클래스이다.
  • 두개의 클래스는 Thread안전성의 차이 (StringBuffer는 안전 하지만 속도가 느림, StringBuilder 안전하지 않고 속도가 빠름) 가 있다함 (본인은 아직 이 Thread의 안전성에 대해서 잘 모르겠음)
  • 앞서 이야기한 String은 불변성과 공유성을 가지고 있기 때문에 문자열을 변경시키는 경우가 많을 때, StringBuffer 나 StringBuilder가 더 성능이 좋다!
public class Main {
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer();
        System.out.println(sb); // ""
        // .append(값) 을 통해 뒤로 이어 붙히기
        sb.append("이게 StringBuffer야");
        System.out.println(sb); // "이게 StringBuffer야"
        // .length() 를 통한 길이 확인
        System.out.println(sb.length());    //16

        // .insert(인덱스, 값)
        sb.insert(3, "진짜 "); // "이게 진짜 StringBuffer야"
        System.out.println(sb);

        // .substring(인덱스, 인덱스)
        System.out.println(sb.substring(3, 6)); //진짜
        System.out.println(sb);     //이게 진짜 StringBuffer야

        //.delete(인덱스, 인덱스)
        sb.delete(3, 6);
        System.out.println(sb); // "이게 StringBuffer야"

        //.replace(인덱스, 인덱스, 값)
        sb.replace(0, 2, "진짜");
        System.out.println(sb); // "진짜 StringBuffer야"


        // .reverse()
        sb.reverse();
        System.out.println(sb); // "야reffuBgnirtS 짜진"
    }
}
  • 위 정리한 코드 처럼 StringBuffer는 이러한 메소드 들로 동작한다.
  • StringBuilder도 StringBuilder가 하는 모든 동작들을 지원한다.

StringTokenizer 란?

  • 문자열을 우리가 지정한 구분자로 분리해주는 클래스로 쪼개진 문자열을 Token 이라고 부른다.
  • java.util.StringTokenizer를 import해야 사용할 수 있고 밑에는 사용 예제 이다.
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args){
        String str1 = "12:34:56";
        StringTokenizer tokenizer = new StringTokenizer(str1, ":");

        //.countTokens() => 토큰의 갯수를 반환해줌
        System.out.println("토큰 개수: " + tokenizer.countTokens());    //3

        // .hasMoreTokens() => 남아 있는 token 이 있는지 여부 true/false
        while(tokenizer.hasMoreTokens()){
            // .nextToken() Tokenizer가 가지고 있는 하나의 토큰을 반환
            System.out.println(tokenizer.nextToken());
        }
        
    }
}
  • 만약 .nextToken()메소드를 사용했는데 토큰이 남아있지 않다면 NoSuchElementException 이 발생되기 때문에 hasMoreToken() 메소드로 먼저 확인해보고 값을 불러오도록 한다.
728x90
반응형
LIST