문자열을 저장하는 String은 내부의 문자열을 수정할 수 없다. 예를 들어서 String의 replace() 메소드는 대치된 새로운 문자열을 리턴하는 것이지 내부 문자열을 대치하는 것이 아니다.
+ 연산에도 마찬가지 이다.
String str1 ="abc";str1+="defg";
는 "abc"객체는 그대로 있고, "abcdefg"의 새로운 객체가 생성된 후 새로 생성된 객체를 참조하게 된다.
문자열을 결합하는 + 연산자를 많이 사용하면 할수록 그만큼 String 객체의 수가 늘어나기 때문에 프로그램 성능을 느리게 하는 요인이 된다.
문자열을 변경하는 작업이 많을 경우에는 String 클래스를 사용하는 것보다 StringBuffer, StringBuilde 클래스를 사용하는 것이 좋다. 이 두 클래스는 내부 Buffer(:데이터를 임시로 저장하는 메모리)에 문자열을 저장해두고, 그 안에서 추가, 수정, 삭제 작업을 할 수 있도록 설계되어 있다. 즉, String처럼 새로운 객체를 만들지 않고도 문자열을 조작할 수 있는 것이다.
두 클래스의 사용방법은 동일하나 차이점은 **StringBuffer는 멀티 스레드 환경에서 사용할 수 있도록 동기화가 적용되어 있어 멀티 스레드에 안전(thread-safe)**하지만, StringBuilder 는 단일 스레드 환경에서만 사용하도록 설계되어 있다.
StringBuilder
// 16개 문자들을 저장할 수 있는 초기버퍼StringBuilder sb =newStringBuilder();//주어진 개수만큼 문자들을 저장할 수 있는 초기 버퍼StringBuilder sb =newStringBuilder(16);// 주어진 str매개값을 버퍼의 초기값으로 저장StringBuilder sb =newStringBuilder("Java");
버퍼가 부족할 경우 자동으로 버퍼 크기를 늘리기 때문에 초기 버퍼의 크기는 그다지 중요하지 않다.
append와 insert 메소드는 매개변수가 다양한 타입으로 오버로딩 되어 있으므로 대부분 값을 문자로 추가, 삽입할 수 있다.
StringBuilder sb =newStringBuilder();sb.append("JAVA ");sb.append("Programming");// 버퍼에 있는 것을 String타입으로 리턴sb.toString();sb.insert(4,"2");//=>JAVA2 Programmingsb.setCharAt(4,'6');//=>JAVA6 Programmingsb.replace(6,17,"Book");//=>JAVA6 Booksb.delete(4,5);//=>JAVA Book
StringBuilder와 StringBuffer의 결과 값이 다른 것을 볼 수 있다. 이는 thread들이 동시에 StringBuilder 클래스에 접근할 수 있어 더 작은 수가 나온 것이다. String Buffer는 multi-thread 환경에서 다른 값을 변경하지 못하도록 동기화(Synchronization)되어있다.
그러므로 Web이나 Socket과 같이 비동기로 동작하는 경우가 많을때는 StringBuffer를 사용하는 것이 안전하다.