String on String Literals의 intern 메서드는 언제 사용해야 합니까?
String #intern()에 따르면intern
메서드는 String 풀에 String이 있는 경우 String 풀에서 String을 반환하도록 되어 있습니다.그렇지 않으면 String 풀에 새로운 String 개체가 추가되어 이 String의 참조가 반환됩니다.
그래서 이렇게 해봤어요
String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
if ( s1 == s2 ){
System.out.println("s1 and s2 are same"); // 1.
}
if ( s1 == s3 ){
System.out.println("s1 and s3 are same" ); // 2.
}
그럴 줄 알았어s1 and s3 are same
s3가 삽입되면 인쇄됩니다.s1 and s2 are same
인쇄되지 않습니다.그 결과, 양쪽의 행이 인쇄됩니다.즉, 기본적으로 String 상수가 삽입됩니다.하지만 만약 그렇다면, 왜 우리는 그 정보가intern
방법?즉, 이 방법을 언제 사용해야 합니까?
Java는 String Literals를 자동으로 인턴으로 만듭니다.즉, 대부분의 경우 == 연산자는 ints 또는 기타 원시 값과 동일한 방식으로 Strings에 대해 작동하는 것으로 보입니다.
문자열 리터럴의 경우 인터닝이 자동으로 이루어지므로intern()
method는 다음과 같이 구성된 문자열에 사용됩니다.new String()
예를 들어 다음과 같습니다.
String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").intern();
if ( s1 == s2 ){
System.out.println("s1 and s2 are same"); // 1.
}
if ( s1 == s3 ){
System.out.println("s1 and s3 are same" ); // 2.
}
if ( s1 == s4 ){
System.out.println("s1 and s4 are same" ); // 3.
}
if ( s1 == s5 ){
System.out.println("s1 and s5 are same" ); // 4.
}
를 반환합니다.
s1 and s2 are same
s1 and s3 are same
s1 and s5 are same
이외의 모든 경우에 있어서s4
variable을 사용하여 명시적으로 작성된 값new
연산자와 장소intern
메서드는 결과에 사용되지 않았습니다. JVM의 문자열 상수 풀을 반환하는 단일 불변 인스턴스입니다.
자세한 내용은 Java Technikes "String Equality and Interning"을 참조하십시오.
최근 프로젝트에서는 일부 대규모 데이터 구조가 데이터베이스에서 읽혀진 데이터(따라서 문자열 상수/리터럴이 아님)로 설정되었지만, 엄청난 양의 중복이 발생했습니다.그것은 은행 어플리케이션이었고, 수수한 회사 이름(약 100, 200개) 같은 것들이 곳곳에 있었다.데이터 구조는 이미 컸고, 만약 그 모든 회사 이름이 고유한 개체였다면 메모리 오버플로였을 것입니다.대신 모든 데이터 구조에는 동일한 100 또는 200개의 String 객체에 대한 참조가 있으므로 공간을 많이 절약할 수 있습니다.
내장 Strings의 또 다른 작은 장점은 다음과 같습니다.==
관련된 모든 문자열이 확실히 삽입될 경우 스트링을 비교하기 위해 사용할 수 있습니다(성공적!).보다 슬림한 구문과 별도로 이 또한 성능 향상입니다.그러나 다른 사람들이 지적한 바와 같이, 이 작업을 수행하면 프로그래밍 오류가 발생할 위험이 크므로, 이는 최후의 수단으로만 수행되어야 합니다.
단점은 스트링을 삽입하는 데 단순히 힙에 넣는 것보다 시간이 더 오래 걸리고 삽입된 스트링의 공간이 Java 구현에 따라 제한될 수 있다는 것입니다.이 방법은 중복되는 문자열 수가 많은 알려진 적절한 수의 문자열을 처리할 때 가장 적합합니다.
제 2센트를 더하고 싶습니다.==
끈으로 묶어서요
제일 먼저String.equals
하고 있다this==object
.
따라서 약간의 퍼포먼스 향상(메서드라고 부르는 것이 아님)이 있지만 유지보수 담당자의 관점에서 보면==
일부 내부 문자열은 비 내부 문자열이 되는 경향이 있기 때문에 악몽입니다.
그래서 나는 특별한 경우에 의존하지 말 것을 제안한다.==
interned string의 경우, 단, 항상equals
고슬링의 의도대로.
EDIT: 인턴이 비인턴이 됨:
V1.0
public class MyClass
{
private String reference_val;
...
private boolean hasReferenceVal ( final String[] strings )
{
for ( String s : strings )
{
if ( s == reference_val )
{
return true;
}
}
return false;
}
private void makeCall ( )
{
final String[] interned_strings = { ... init with interned values ... };
if ( hasReference( interned_strings ) )
{
...
}
}
}
버전 2.0에서는 유지보수는 다음을 수행하기로 결정했습니다.hasReferenceVal
일련의 내부 문자열이 있을 것으로 예상하는 세부 사항은 자세히 설명하지 않고 공개합니다.
V2.0
public class MyClass
{
private String reference_val;
...
public boolean hasReferenceVal ( final String[] strings )
{
for ( String s : strings )
{
if ( s == reference_val )
{
return true;
}
}
return false;
}
private void makeCall ( )
{
final String[] interned_strings = { ... init with interned values ... };
if ( hasReference( interned_strings ) )
{
...
}
}
}
대부분의 경우 배열에 리터럴 값이 포함되어 있고 경우에 따라서는 리터럴 이외의 문자열이 사용되기 때문에 버그를 발견하기는 매우 어려울 수 있습니다.한다면equals
대신 사용되었습니다.==
그리고나서hasReferenceVal
계속 일을 했을 겁니다.다시 말하지만 성능 향상은 미미하지만 유지 보수 비용이 높습니다.
Java String Internal 학습 - 한 번 모두
Java의 문자열은 설계상 불변의 객체입니다.따라서 같은 값을 가진 두 개의 문자열 개체는 기본적으로는 서로 다른 개체입니다.단, 메모리를 절약하려면 string intern이라는 개념으로 같은 메모리를 사용하도록 지정할 수 있습니다.
다음 규칙은 개념을 명확하게 이해하는 데 도움이 됩니다.
- 문자열 클래스는 처음에 비어 있는 intern-pool을 유지합니다.이 풀은 고유한 값만 포함하는 문자열 개체를 포함해야 합니다.
- 값이 같은 문자열 리터럴은 모두 동일한 메모리 위치 객체로 간주해야 합니다.이러한 문자열 리터럴에는 구별 개념이 없기 때문입니다.따라서 같은 값을 가진 모든 리터럴은 intern-pool에 단일 엔트리를 만들고 동일한 메모리 위치를 참조합니다.
- 두 개 이상의 리터럴을 연결하는 것도 문자 그대로입니다.(따라서 규칙 #2가 적용됩니다.)
- 오브젝트로 작성된 각 문자열(즉, 리터럴 이외의 다른 메서드에 의해)은 다른 메모리 위치를 가지며 intern-pool에 엔트리를 작성하지 않습니다.
- 리터럴과 비 리터럴을 연결하면 비 리터럴이 됩니다.따라서 결과 개체는 새로운 메모리 위치를 가지며 intern-pool에 엔트리를 작성하지 않습니다.
- 문자열 개체에서 intern 메서드를 호출하면 intern-pool에 들어가는 새 개체를 만들거나 동일한 값을 가진 풀에서 기존 개체를 반환합니다.intern-pool에 없는 오브젝트에 대한 호출은 오브젝트를 풀로 이동시키지 않습니다.오히려 풀에 들어가는 다른 개체를 만듭니다.
예:
String s1=new String (“abc”);
String s2=new String (“abc”);
If (s1==s2) //would return false by rule #4
If (“abc” == “a”+”bc” ) //would return true by rules #2 and #3
If (“abc” == s1 ) //would return false by rules #1,2 and #4
If (“abc” == s1.intern() ) //would return true by rules #1,2,4 and #6
If ( s1 == s2.intern() ) //wound return false by rules #1,4, and #6
주의: string intern의 동기 부여 사례에 대해서는 여기서 설명하지 않습니다.다만, 메모리의 절약이 주된 목적의 하나가 되는 것은 확실합니다.
문자열 리터럴 및 상수는 기본적으로 삽입됩니다.그것은,"foo" == "foo"
Literals에 됨), (String Literals) "",new String("foo") != new String("foo")
.
컴파일 시간과 런타임 시간이라는 두 개의 기간을 작성해야 합니다.예를 들어 다음과 같습니다.
//example 1
"test" == "test" // --> true
"test" == "te" + "st" // --> true
//example 2
"test" == "!test".substring(1) // --> false
"test" == "!test".substring(1).intern() // --> true
한편 예제 1에서는 결과가 모두 true로 반환됩니다.왜냐하면 컴파일 시간 동안 jvm은 "test"를 리터럴 문자열 풀에 넣기 때문입니다.jvm find "test"가 존재하는 경우 기존 문자열이 사용됩니다.예 1에서는 "test" 문자열은 모두 동일한 메모리 주소를 가리키므로 예제 1은 true를 반환합니다.한편, 예 2에서, "test" == "!test".substring(1)의 경우, 서브스트링() 메서드는 런타임에 실행되며, "test" == "!test" 및 "!test"의 경우 풀은 두 개의 문자열 오브젝트를 생성하므로 서로 다른 참조 오브젝트이므로, 이 경우 false를 반환합니다. internal 메서드의 p."!test".testring(1)을 리터럴 문자열 풀로 보냅니다.따라서 이 경우 두 문자열은 동일한 참조 개체이므로 true를 반환합니다.
http://en.wikipedia.org/wiki/String_interning
string interning은 각 개별 문자열 값의 복사본을 1개만 저장하는 방식이며, 이는 불변해야 합니다.문자열을 인터닝하면 일부 문자열 처리 태스크의 시간 또는 공간 효율이 향상되지만 문자열 작성 또는 삽입 시 시간이 더 소요됩니다.고유한 값은 문자열 내부 풀에 저장됩니다.
내부 문자열은 중복되는 문자열을 방지합니다.인터닝을 통해 중복된 문자열을 검출하고 대체하기 위해 더 많은 CPU 시간을 소비하면서 RAM을 절약할 수 있습니다.참조의 수에 관계없이 삽입된 각 String의 복사본은 1개뿐입니다.Strings는 불변하기 때문에 두 개의 다른 메서드가 우연히 같은 String을 사용하는 경우 동일한 String의 복사본을 공유할 수 있습니다.중복된 문자열을 공유 문자열로 변환하는 프로세스를 인터닝이라고 합니다.String.intern()은 표준 마스터 String의 주소를 제공합니다.내장된 문자열을 String의 문자를 하나씩 비교하는 등가 대신 단순 ==(포인터 비교)와 비교할 수 있습니다.문자열은 불변하기 때문에 예를 들어 "hippotomus"와 같은 다른 리터럴의 하위 문자열로 존재하는 경우 "pot"에 대해 별도의 문자열 리터럴을 생성하지 않음으로써 intern 프로세스는 공간을 더 절약할 수 있습니다.
자세한 것은, http://mindprod.com/jgloss/interned.html 를 참조해 주세요.
String s1 = "Anish";
String s2 = "Anish";
String s3 = new String("Anish");
/*
* When the intern method is invoked, if the pool already contains a
* string equal to this String object as determined by the
* method, then the string from the pool is
* returned. Otherwise, this String object is added to the
* pool and a reference to this String object is returned.
*/
String s4 = new String("Anish").intern();
if (s1 == s2) {
System.out.println("s1 and s2 are same");
}
if (s1 == s3) {
System.out.println("s1 and s3 are same");
}
if (s1 == s4) {
System.out.println("s1 and s4 are same");
}
산출량
s1 and s2 are same
s1 and s4 are same
String p1 = "example";
String p2 = "example";
String p3 = "example".intern();
String p4 = p2.intern();
String p5 = new String(p3);
String p6 = new String("example");
String p7 = p6.intern();
if (p1 == p2)
System.out.println("p1 and p2 are the same");
if (p1 == p3)
System.out.println("p1 and p3 are the same");
if (p1 == p4)
System.out.println("p1 and p4 are the same");
if (p1 == p5)
System.out.println("p1 and p5 are the same");
if (p1 == p6)
System.out.println("p1 and p6 are the same");
if (p1 == p6.intern())
System.out.println("p1 and p6 are the same when intern is used");
if (p1 == p7)
System.out.println("p1 and p7 are the same");
되면 2개의 스트링이 됩니다.intern()
를 사용하면 비교가 가능합니다.또, 이전에는 참조가 존재하지 않았던 경우는, 문자열 풀에 참조를 작성할 수 있습니다.
「 」를 사용하는 String s = new String(hi)
의 새 단, java를 사용하는 ,String s = "hi"
"hi의 인스턴스가 만 반환합니다java는 "hi"를 "hi"로 지정합니다.
하고 있기 에, 「」는 에 근거하고 있습니다.intern()
는 참조 작성에 도움이 되며 문자열의 내용을 비교할 수 있습니다.
「 」를 사용하는 intern()
코드에서는 같은 오브젝트를 참조하는 문자열에서 사용되는 공간을 클리어하고 메모리 내의 이미 존재하는 동일한 오브젝트의 참조만 반환합니다.
그러나 p5를 사용하는 경우:
String p5 = new String(p3);
p3의 내용만 복사하고 p5를 새로 만듭니다.그래서 그것은 인턴이 아니다.
따라서 출력은 다음과 같습니다.
p1 and p2 are the same
p1 and p3 are the same
p1 and p4 are the same
p1 and p6 are the same when intern is used
p1 and p7 are the same
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1 = "test";
String s2 = new String("test");
System.out.println(s1==s2); //false
System.out.println(s1==s2.intern()); //true --> because this time compiler is checking from string constant pool.
}
string intern() 메서드는 문자열 상수 풀에 힙 문자열 개체의 정확한 복사본을 작성하기 위해 사용됩니다.문자열 상수 풀의 문자열 개체는 자동으로 삽입되지만 힙의 문자열 개체는 그렇지 않습니다.intern 작성의 주된 용도는 메모리 공간을 절약하고 문자열 개체를 보다 빠르게 비교하는 것입니다.
출처 : 문자열 intern이 Java로 뭐죠?
대로 그 intern()
method는 String 풀에서 먼저 검색되며, 발견된 경우 해당 개체를 반환하거나 새 String을 풀에 추가합니다.
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hello".intern();
String s4 = new String("Hello");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//true
System.out.println(s1 == s4.intern());//true
s1
★★★★★★★★★★★★★★★★★」s2
'Hello String 'Hello'를 입니다."Hello".intern()
알게 될 s1
★★★★★★★★★★★★★★★★★」s2
"s1 == s3"
true를 합니다.s3.intern()
.
대응하는 문자열 상수 풀 객체 참조를 가져오려면 힙 객체 참조를 사용하여 intern()으로 이동합니다.
String s1 = new String("Rakesh");
String s2 = s1.intern();
String s3 = "Rakesh";
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // true
스텝 1: 데이터가 'Rakesh'인 오브젝트가 히프 및 문자열 상수 풀에 생성됩니다.또한 s1은 항상 힙오브젝트를 가리키고 있습니다.
스텝 2: 힙 오브젝트 참조 s1을 사용하여 intern()을 사용하여 대응하는 문자열 상수 풀 오브젝트 참조 s2를 취득하려고 합니다.
순서 3: 문자열 상수 풀에 데이터 'Rakesh'가 포함된 개체를 의도적으로 만듭니다(이름 s3 참조).
"==" 연산자는 참조 비교를 의미합니다.
s1==s2에 대해 false를 얻는 중
s2==s3에 대한 실현
이게 도움이 되었으면 좋겠어!!
언급URL : https://stackoverflow.com/questions/1855170/when-should-we-use-intern-method-of-string-on-string-literals
'programing' 카테고리의 다른 글
Java에서 Integer와 int의 차이점은 무엇입니까? (0) | 2022.08.09 |
---|---|
커스텀 입력 Vue 컴포넌트를 테스트하는 방법 (0) | 2022.08.09 |
java.time을 변환합니다.localDate를 java.util로 변환합니다.날짜 유형 (0) | 2022.08.09 |
문자열 리터럴의 "Life-time" (C) (0) | 2022.08.09 |
Vue. 생성된 요소의 "key" 특성 값을 가져오는 방법 (0) | 2022.08.09 |