이상한 문자열 풀 동작
이상한 문자열 풀 동작에 대한 질문이 있습니다. ==
동일한 문자열을 비교 하여 그들이 풀에 있는지 여부를 확인하는 데 사용하고 있습니다.
public class StringPoolTest {
public static void main(String[] args) {
new StringPoolTest().run();
}
String giveLiteralString() {
return "555";
}
void run() {
String s1 = giveLiteralString() + "";
System.out.println("555" == "555" + "");
System.out.println(giveLiteralString() == giveLiteralString() + "");
}
}
출력은 다음과 같습니다.
true
false
저에게 큰 놀라움입니다. 누구든지 이것을 설명해 주시겠습니까? 나는 이것에 대해 컴파일 시간에 일어나고 있다고 생각합니다. 하지만 ""
문자열에 추가 하는 것이 전혀 차이 가 나는 이유는 무엇입니까?
"555" + ""
A는 컴파일 시간 상수 반면
giveLiteralString() + ""
그렇지 않습니다. 따라서 전자는 문자열 상수 "555"로 컴파일되고 후자는 실제 메서드 호출 및 연결로 컴파일되어 새로운 String 인스턴스가 생성됩니다.
JLS §3.10.5 (문자열 리터럴) 도 참조하십시오 .
런타임에 연결에 의해 계산 된 문자열은 새로 생성되므로 구별됩니다.
이 줄을 디 컴파일 한 후
System.out.println("555" == "555" + "");
나는이 바이트 코드를 얻었다
LINENUMBER 8 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ICONST_1
INVOKEVIRTUAL java/io/PrintStream.println(Z)V
...
이는
System.out.println(true);
이는 표현식 "555" == "555" + ""
이 부울로 컴파일 됨을 의미 합니다 true
.
들어 giveLiteralString() == giveLiteralString() + ""
javac의이 바이트 코드를 내장
LINENUMBER 8 L0
INVOKESTATIC Test1.giveLiteralString()Ljava/lang/String;
NEW java/lang/StringBuilder
DUP
INVOKESTATIC Test1.giveLiteralString()Ljava/lang/String;
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
IF_ACMPNE L1
...
이는
if (giveLiteralString() == new StringBuilder(giveLiteralString()).append("").toString()) {
...
두 개의 별개의 객체를 비교하기 때문에 항상 거짓을 생성합니다.
두 번째 경우 컴파일러 는 길이가 0 인 것으로 알려진 컴파일 시간 값 + ""
이기 때문에 정렬이 불가능 하다는 것을 인식 ""
할 수있었습니다. 그러나 컴파일러는 여전히 giveLiteralString
null에 대한 결과를 확인해야하므로 ( +
최적화되지 않은 경우 작업 의 결과로 null 검사가 발생 하기 때문에) 최적화를 시도하지 않는 것이 가장 간단합니다.
As a result, the compiler generates code to perform the concatenation, and a new string is created.
Compile Time Concatenation String computed by constant expression are done at compile time and treated as constants or literals means the value of the string or expression is known or evaluated at compile time hence the compiler can check the same value in string pool and the return the same string object reference.
Runtime Concatenation String expressions whose values are known or can not be evaluated at compile but depends on the input or condition of run-time then the compiler will not know the value of the string and hence always land up using StringBuilder to append the string and always returns a new string . I guess this example will clarify it better.
public static void main(String[] args) {
new StringPoolTest().run();
}
String giveLiteralString() {
return "555";
}
void run() {
System.out.println("555" + 9 == "555" + 9);
System.out.println("555"+Integer.valueOf(9) == "555" + Integer.valueOf(9));
System.out.println(giveLiteralString() == giveLiteralString());
// The result of runtime concatenation is a fresh string.
System.out.println(giveLiteralString() == giveLiteralString() + "");
}
참고URL : https://stackoverflow.com/questions/17525210/strange-string-pool-behavior
'Program Tip' 카테고리의 다른 글
matplotlib에서 두 번째 x 축을 추가하는 방법 (0) | 2020.10.26 |
---|---|
pip 종속성 / 요구 사항을 나열하는 방법이 있습니까? (0) | 2020.10.26 |
AVAudioPlayer로 사운드 재생 (0) | 2020.10.26 |
Spark에서 드라이버의 Python 버전을 어떻게 설정합니까? (0) | 2020.10.26 |
턴 기반 게임 서버에 대한 웹 소켓과 긴 폴링의 차이점 (0) | 2020.10.26 |