String str = "java" + 8 + " study";
먼저 이렇게 문자열 대상으로 + 연산이 가능한 이유는 자바 컴파일러가 + 연산을 기존에 구현되어있던 방법으로 변환해주기 때문이다.
그렇다면 구체적으로 어떤 방법으로 변환해주는 걸까?
과거 JDK 버전에서는 이를,
String str = "java".concat(String.valueOf(8)).concat(" study");
위와 같이 변환해줬다. 위 방식에는 아래와 같은 문제점이 있다.
1. 위 예시에서는 숫자 8과 같이 기존에 String이 아닌 자료형을 매번 String.valueOf() 메소드를 호출하여 변환하게 된다.
2. String.concat() 메소드는 concatenate 동작 수행 후 매번 새로운 String 인스턴스를 반환한다.
하지만 JDK1.5 버전 이후 부터 위 방식의 문제점을 해결하고자 + 연산에 대한 내부 동작이 변경되었다.
StringBuilder는 내부적으로 문자열을 저장하기 위한 메모리 공간을 지니는데, String과 달리 해당 공간에 대해 문자를 추가하거나 삭제하는 것이 가능하다.
미리 메모리 공간이 정해져있으며, 필요 시 알아서 공간을 늘리는 작업을 하는데 해당 작업이 자원의 소모가 많은 작업이다.
문자열 + 연산이 컴파일러에 의해 StringBuilder를 사용하는 방식으로 변경되었는데 그 방법은 아래와 같다.
String str = (new StringBuilder("java").append(8).append(" study")).toString();
1. 마지막에 딱 한 번의 toString()의 호출로 String.concat()의 계속해서 일어나는 타입 변환 문제를 해결했다.
2. 이 때, StringBuilder.append() 의 수행 결과는 새로운 인스턴스가 아니라 기존 인스턴스에 append() 안에 있는 매개변수를 붙인 것이다. 따라서 새로운 인스턴스를 생성하지 않는다.
결과적으로 + 연산의 내부 구현 방식이 변경되면서 기존 문제점이 해결됐다고 볼 수 있는데,
그럼에도 불구하고 + 연산이 StringBuilder로 변환되는 과정이 있으므로 StringBuilder를 직접적으로 사용하는 것 보다는 성능이 느릴 것이다.
따라서 문자열 결합을 엄청나게 많이 수행해야 한다면 StringBuilder를 직접 사용하여 append => toString()하는 것이 나을 것이다. 하지만 그렇지 않다면..내부 동작이 개선된 + 연산을 편하게 사용하면 되지 않을까 싶다.
끗.