public class StringReplace
{
private String source ="";
private int length;
private StringBuffer buffer;
public StringReplace(String source) {
this.source = source; // 전달받는 문자열로 초기화
length = source.length(); // source의 길이로 초기화
buffer = new StringBuffer(length + 100); // 버퍼(저장공간)의 크기는 length+100으로
}
public int length() {
return length;
}
public String replace(String old, String nw) {
return replace(old, nw, 0);
}
public String replace(String old, String nw, int pos) {
int index = 0;
if (old == null || nw == null)
return "null";
if ( (index = source.indexOf(old, pos))!=-1) {/*
source는 String타입이였으니 String타입의 메서드 indexOf를 찾아보자. 이와 관련된 두 개의 메서드를 찾을 수 있었다.
1. int indexOf (int ch) 2. int indexOf (String str) ( O )
위 매개변수에서 old가 string값이므로 이게 맞을 것이다. 해석하자면, "111"이라는 문자열이 source내에 존재하는지 검사한다.
있으면 int(정수) 타입의 숫자를 반환할 것이고
없으면 -1을 반환한다.
따라서 위 코드 index = source.indexOf(old, pos) ! = -1 이라는 의미는 곧
"000111222333111222333" 에서 "111"을 찾는다.
"111"이 있으면 index에 정수값을 저장할 것이다. ( ☆ 여기서는 index에 3과 12를 저장 ☆)
"111"이 없으면 index에 -1 을 저장할 것이다.
<첫번째 사이클에서 index = 3 , 두번째 사이클에서 index = 12가 저장됨>
그런데 != -1은 곧, "111"을 찾았다면! 아래 코드 buffer.append를 수행하라는 의미이다.
*/
buffer.append(source.substring(pos, index));
먼저 첫번째는 buffer.append(source.substring (0, 3))이 된다.
즉, pos(=0)부터 index(=3) 미만까지 잘라서 버퍼에 저장하라는 이야기다. ( 0 이상 3 미만 )
따라서 첫번째 출력값은 000이 나오게 된다.
buffer.append(nw);
여기에 buffer.append(nw) 를 통해서 "AAA"를 이어 붙인다.
따라서 첫번째 출력값은 000AAA가 나오게 된다.
replace(old, nw, index + old.length());
첫번째 싸이클 index(=0) + old.length (=3) = 3 두번째 싸이클 index(=3) + old.length (=3) = 6
} else {
// 더 이상 치환할 문자열을 못 찾으면 나머지 문자열을 buffer에 저장한다.
buffer.append(source.substring(pos));
}
return buffer.toString();
첫번째 버퍼의 저장된 값 000AAA를 문자열로 반환한다.
}
public static void main(String[] args) {
String str = "000111222333111222333";
System.out.println(str);
StringReplace sc = new StringReplace(str);
System.out.println(sc.replace("111", "AAA"));
}
이번 코드를 분석하면서 깨달은 점
1. StringReplace라는 클래스를 만들었는데, 인스턴스를 생성하지 않으면 말짱 도루묵이라는 것.
따라서 메인 메서드에서 StringReplace라는 new연산자를 이용해 만들었고, 참조변수 sc가 이를 가리킨다.
StringReplace sc = new StringReplace (str) ;
여기서 매개변수(str)가 있는 생성자라는 점을 인지해야 한다.
2. 멤버변수를 보면 String타입의 source와, StringBuffer타입의 buffer 그리고 int타입의 length가 있다.
여기서 String, StringBuffer는 인스턴스 생성없이! 바로 메서드를 이용할 수 있다.
int는 이렇게 안된다.
3. StringBuffer 반환타입에 대해서
a,b,c만 따로 출력하면 aa, bb, cc를 나타내지만
a.append(b) 이후에는 a가 aabb를 출력한다.
StringBuffer append (int i) 처럼 반환형이 StringBuffer인 메서드들이 있다.
이 메서드는 실행부 이후 새로운 StringBuffer 객체를 반환하지 않는다.
메소드의 객체 자신이 다시 반환된다.
예를 들어 해시코드가 "1234"인 StringBuffer a 객체가 있으면
a.append("bb") 구문을 실행한 뒤 반환되는 StringBuffer 객체의 해시코드는 여전히 "1234"이다.
위와같이 코드를 구성하면 JVM에는 새로운 String 객체가 계속해서 생겨난다.
이럴 때 StringBuffer 클래스를 이용하면 하나의 객체에서만 작업이 이루어진다.
따라서 메모리 효율적인 방법이다.
위와 같이 변경한 코드의 특징을 보면 append이후에 append메소드가 이어진다는 것이다.
append() 메서드를 연달아 사용해도 되는 이유는 "메소드 실행 이후 자기 자신의 객체를 반환"하기 떄문이다. 즉, StringBuffer 하나에서만 수정이 이루어진다.
'프로그래밍 > 코드분석' 카테고리의 다른 글
자바의 정석 연습문제 6-2 (0) | 2016.08.16 |
---|---|
자바의 정석 연습문제 9-4 (0) | 2016.08.13 |
자바의 정석 연습문제 9-3 (0) | 2016.08.13 |
자바의 정석 연습문제 9-1 (0) | 2016.08.13 |
자바의 정석 8-9 코드분석 (0) | 2016.08.09 |