Java의 intern() 메소드에 대한 심층 분석
1. 문자열 문제
문자열은 실제로 일상적인 코딩 작업에 매우 유용하며 사용하기가 비교적 간단하므로 이에 대해 자세히 설명하는 사람은 거의 없습니다. 연구. 반면에 면접이나 필기 시험은 더 깊이 있고 어려운 질문이 포함되는 경우가 많습니다. 채용 시 후보자에게 가끔 관련 질문을 하는 것은 답변이 특히 정확하고 심층적이어야 한다는 의미는 아닙니다. 일반적으로 이러한 질문을 하는 목적은 첫 번째는 기본 지식에 대한 이해를 테스트하는 것입니다. 두 번째는 JAVA에 대한 기본 지식을 테스트하는 것입니다. 두 번째는 기술에 대한 지원자의 태도를 테스트하는 것입니다.
다음 프로그램이 어떤 결과를 출력하는지 볼까요? 모든 질문에 올바르게 대답하고 그 이유를 알 수 있다면 이 기사는 별로 의미가 없을 것입니다. 대답이 틀리거나 원리가 명확하지 않다면 다음 분석을 자세히 살펴보십시오. 이 기사는 각 프로그램의 결과와 결과를 출력하는 깊은 이유를 명확하게 이해하는 데 도움이 될 것입니다.
코드 세그먼트 1:
package com.paddx.test.string; public class StringTest { public static void main(String[] args) { String str1 = "string"; String str2 = new String("string"); String str3 = str2.intern(); System.out.println(str1==str2);//#1 System.out.println(str1==str3);//#2 } }
코드 세그먼트 2:
package com.paddx.test.string; public class StringTest01 { public static void main(String[] args) { String baseStr = "baseStr"; final String baseFinalStr = "baseStr"; String str1 = "baseStr01"; String str2 = "baseStr"+"01"; String str3 = baseStr + "01"; String str4 = baseFinalStr+"01"; String str5 = new String("baseStr01").intern(); System.out.println(str1 == str2);//#3 System.out.println(str1 == str3);//#4 System.out.println(str1 == str4);//#5 System.out.println(str1 == str5);//#6 } }
코드 세그먼트 3(1):
package com.paddx.test.string; public class InternTest { public static void main(String[] args) { String str2 = new String("str")+new String("01"); str2.intern(); String str1 = "str01"; System.out.println(str2==str1);//#7 } }
코드 세그먼트 3(2):
package com.paddx.test.string; public class InternTest01 { public static void main(String[] args) { String str1 = "str01"; String str2 = new String("str")+new String("01"); str2.intern(); System.out.println(str2 == str1);//#8 } }
설명의 편의를 위해 위 코드의 #1~#8 출력 결과를 인코딩하였으며, 아래 파란색 글씨 부분이 그 결과입니다.
2. 문자열 심층 분석
1. 코드 세그먼트 분석 1
문자열은 기본 유형에 속하지 않지만, 기본 유형과 같으며 리터럴을 통해 직접 값을 할당할 수 있습니다. 물론 new를 사용하여 문자열 객체 를 생성할 수도 있습니다. 그러나 리터럴 할당을 통해 문자열을 생성하는 것과 새 문자열을 생성하는 것에는 근본적인 차이가 있습니다.
리터럴 할당을 통해 문자열을 생성하는 경우 상수에 우선순위가 부여됩니다. 동일한 문자열이 풀에 이미 존재하는 경우 스택의 참조 가 해당 문자열을 직접 가리킵니다. 문자열이 없으면 상수 풀에 문자열이 생성됩니다. 스택의 참조는 이 문자열을 가리킵니다. new를 통해 문자열을 생성하면 힙에 문자열 객체가 직접 생성됩니다. (참고로 JDK 7 이후에는 HotSpot이 상수 풀을 영구 생성에서 힙으로 옮겼습니다. 자세한 내용은 "JDK8 메모리를 참조하세요." Model-The Disappearing PermGen" 기사), 스택의 참조는 개체를 가리킵니다. 힙에 있는 문자열 객체의 경우 intern() 메서드를 통해 상수 풀에 문자열을 추가하고 상수에 대한 참조를 반환할 수 있습니다.
이제 코드 세그먼트 1의 결과를 명확하게 이해할 수 있습니다.
결과 #1: str1이 문자열의 상수를 가리키므로 str2는 힙에서 생성된 개체입니다. 따라서 str1==str2는 false를 반환합니다.
결과 #2: str2는 str2의 값("string")을 상수 풀에 복사하는 intern 메서드를 호출하지만 해당 문자열은 이미 상수 풀에 존재합니다(즉, 문자열이 가리키는 문자열). by str1), 문자열에 대한 참조를 직접 반환하므로 str1==str2는 true를 반환합니다.
코드 세그먼트 1을 실행한 결과는 다음과 같습니다.
2. 코드 세그먼트 2 분석
두 번째 코드 세그먼트의 결과는 StringTest01.class 파일을 디컴파일하면 더 쉽게 이해할 수 있습니다.
상수 풀 콘텐츠(부분):
실행 지침( part) , 두 번째 열 #+ordinal은 상수 풀의 항목에 해당합니다):
위의 실행 과정을 설명하기 전에 먼저 두 가지 명령을 이해하세요.
ldc: 런타임 상수 풀에서 항목을 푸시하고, 지정된 항목의 참조를 상수 풀에서 스택으로 로드합니다.
astore_
이제 코드 세그먼트 2의 실행 프로세스를 설명하기 시작합니다.
0: ldc #2: 상수 풀의 두 번째 항목("baseStr")을 스택에 로드합니다.
2: astore_1 : 1의 참조를 첫 번째 지역 변수에 할당합니다. 즉, String baseStr = "baseStr"
3: ldc #2: 상수에서 두 번째 변수를 로드합니다. 풀 항목("baseStr")을 스택에 추가합니다.
5: astore_2: 3의 참조를 두 번째 지역 변수, 즉 final String에 할당합니다. baseFinalStr="baseStr"
6: ldc #3: 첫 번째 문자열을 로드합니다. 상수 풀 세 개의 항목("baseStr01")이 스택에 추가됩니다.
8: astore_3: 6의 참조를 세 번째 지역 변수, 즉 String str1="baseStr01";
에 할당합니다.9: ldc #3: 상수 풀의 세 번째 항목("baseStr01")을 스택에 로드합니다.
11: astore 4: 9의 참조를 네 번째 지역 변수에 할당합니다. String str2="baseStr01";
결과 #3: str1==str2는 둘 다 확실히 true를 반환합니다. str1과 str2는 상수 풀에서 동일한 참조 주소를 가리킵니다. 따라서 실제로 JAVA 1.6 이후에는 상수 문자열의 "+" 연산이 컴파일 단계에서 문자열로 직접 합성됩니다.
13: new #4: StringBuilder의 인스턴스를 생성합니다.
16: dup: 13에서 생성된 객체의 참조를 복사하여 스택에 푸시합니다.
17: Invokespecial #5: 상수 풀의 다섯 번째 항목인 StringBuilder.
위의 세 가지 지침은 StringBuilder 개체를 생성하는 데 사용됩니다.
20: aload_1 : 첫 번째 매개변수 값인 "baseStr"을 로드합니다.
21: Invokevirtual #6: StringBuilder 개체의 추가 메서드를 호출합니다.
24: ldc #7: 상수 풀의 일곱 번째 항목("01")을 스택에 로드합니다.
26: Invokevirtual #6: StringBuilder.append 메서드를 호출합니다.
29: Invokevirtual #8: StringBuilder.toString 메서드를 호출합니다.
32: astore 5: 29의 결과 참조 할당을 다섯 번째 지역 변수, 즉 변수 str3에 대한 할당으로 변경합니다.
결과 #4: str3은 실제로 stringBuilder.append()에 의해 생성된 결과이기 때문에 str1과 같지 않으며 결과는 false를 반환합니다.
34: ldc #3: 상수 풀의 세 번째 항목("baseStr01")을 스택에 로드합니다.
36: astore 6: 34의 참조를 여섯 번째 지역 변수, 즉 str4="baseStr01";
결과 #5: str1과 str4가 상수를 가리키기 때문에 세 번째 항목이 풀에 있으므로 str1==str4는 true를 반환합니다. 여기서도 final 필드의 경우 상수 교체가 컴파일 타임에 직접 수행되는 반면, non-final 필드의 경우 런타임에 할당 처리가 수행되는 현상도 확인할 수 있습니다.
38: new #9: 문자열 객체 생성
41: dup: 참조를 복사하여 스택에 푸시합니다.
42: ldc #3: 상수 풀의 세 번째 항목("baseStr01")을 스택에 로드합니다.
44: Invokespecial #10: String."
47: Invokevirtual #11: String.intern 메서드를 호출합니다.
38번부터 41번까지 해당 소스코드는 new String(“baseStr01″).intern()입니다.
50: astore 7: 47단계에서 반환된 결과를 변수 7에 할당합니다. 즉, str5는 상수 풀에서 baseStr01의 위치를 가리킵니다.
결과 #6: str5와 str1이 모두 상수 풀의 동일한 문자열을 가리키므로 str1==str5는 true를 반환합니다.
코드 세그먼트 2를 실행하면 출력 결과는 다음과 같습니다.
3. 코드 세그먼트 3 분석:
코드 세그먼트 3의 경우 JDK 1.6과 JDK 1.7에서 실행 결과가 다릅니다. 먼저 실행 결과를 살펴보고 그 이유를 설명하겠습니다.
JDK 1.6에서 실행 결과:
JDK 1.7에서 실행 결과:
코드 세그먼트 1의 분석에 따르면 str2와 str1은 원래 다른 위치를 가리키고 false를 반환해야 하기 때문에 JDK 1.6의 결과를 쉽게 얻을 수 있습니다.
이상한 문제는 JDK 1.7 이후에는 첫 번째 경우에는 true를 반환하지만 위치를 변경한 후에는 반환 결과가 false가 된다는 점입니다. 그 주된 이유는 JDK 1.7 이후 HotSpot이 상수 풀을 영구 생성에서 메타 공간으로 옮겼기 때문입니다. 이로 인해 JDK 1.7 이후의 인턴 방식은 구현에 있어 상대적으로 큰 변화를 겪었습니다. 로 이동하여 이 이미 상수 풀에 존재하는지 쿼리하고, 존재하는 경우 상수 풀에 참조를 반환합니다. 이는 이전과 다르지 않습니다. 상수 풀에서 찾을 수 없으면 문자열은 더 이상 상수 풀에 복사되지 않지만 원래 문자열에 대한 참조는 상수 풀에 생성됩니다. 그래서:
결과 #7: 첫 번째 경우에는 상수 풀에 문자열 "str01"이 없기 때문에 힙의 "str01"에 대한 참조가 상수 풀에 생성되고, 이를 수행할 때 리터럴 할당의 경우 상수 풀이 이미 존재하므로 참조를 직접 반환할 수 있습니다. 따라서 str1과 str2는 모두 힙의 문자열을 가리키고 true를 반환합니다.
결과 #8: 위치를 교환한 후 리터럴 할당(String str1 = "str01")을 수행할 때 상수 풀이 존재하지 않기 때문에 str1은 상수 풀의 위치를 가리키고 str2는 힙을 가리킵니다. intern 메소드는 의 객체에 사용되며 str1 및 str2에는 영향을 미치지 않으므로 false가 반환됩니다.
[관련 추천]
3. Java에서 intern 메소드의 개념은 무엇인가요
5. String 객체의 intern()에 대한 자세한 설명
위 내용은 Java의 intern() 메소드에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Java의 Weka 가이드. 여기에서는 소개, weka java 사용 방법, 플랫폼 유형 및 장점을 예제와 함께 설명합니다.

Java의 Smith Number 가이드. 여기서는 정의, Java에서 스미스 번호를 확인하는 방법에 대해 논의합니다. 코드 구현의 예.

이 기사에서는 가장 많이 묻는 Java Spring 면접 질문과 자세한 답변을 보관했습니다. 그래야 면접에 합격할 수 있습니다.

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다

Java의 TimeStamp to Date 안내. 여기서는 소개와 예제와 함께 Java에서 타임스탬프를 날짜로 변환하는 방법에 대해서도 설명합니다.

캡슐은 3 차원 기하학적 그림이며, 양쪽 끝에 실린더와 반구로 구성됩니다. 캡슐의 부피는 실린더의 부피와 양쪽 끝에 반구의 부피를 첨가하여 계산할 수 있습니다. 이 튜토리얼은 다른 방법을 사용하여 Java에서 주어진 캡슐의 부피를 계산하는 방법에 대해 논의합니다. 캡슐 볼륨 공식 캡슐 볼륨에 대한 공식은 다음과 같습니다. 캡슐 부피 = 원통형 볼륨 2 반구 볼륨 안에, R : 반구의 반경. H : 실린더의 높이 (반구 제외). 예 1 입력하다 반경 = 5 단위 높이 = 10 단위 산출 볼륨 = 1570.8 입방 단위 설명하다 공식을 사용하여 볼륨 계산 : 부피 = π × r2 × h (4

Spring Boot는 강력하고 확장 가능하며 생산 가능한 Java 응용 프로그램의 생성을 단순화하여 Java 개발에 혁명을 일으킨다. Spring Ecosystem에 내재 된 "구성에 대한 협약"접근 방식은 수동 설정, Allo를 최소화합니다.
