programing

"text"와 새로운 String("text")의 차이점은 무엇입니까?

prostudy 2022. 8. 15. 09:45
반응형

"text"와 새로운 String("text")의 차이점은 무엇입니까?

다음 두 문장의 차이점은 무엇입니까?

String s = "text";

String s = new String("text");

new String("text");명시적으로 새로운 참조상 구별되는 인스턴스를 작성하다String; 「」String s = "text";사용 가능한 경우 문자열 상수 풀의 인스턴스를 재사용할 수 있습니다.

거의 사용하지 않으실 겁니다.new String(anotherString)API 서 :

String(String original) : 새로 생성된 를 초기화합니다. String인수와 같은 문자 시퀀스를 나타내도록 오브젝트를 지정합니다.즉, 새로 생성된 문자열은 인수 문자열의 복사본입니다.원본의 명시적 복사가 필요하지 않는 한 문자열은 불변이므로 이 생성자를 사용할 필요가 없습니다.

관련 질문


참조 구분이란 어떤 의미입니까?

다음의 스니펫을 조사합니다.

    String s1 = "foobar";
    String s2 = "foobar";

    System.out.println(s1 == s2);      // true

    s2 = new String("foobar");
    System.out.println(s1 == s2);      // false
    System.out.println(s1.equals(s2)); // true

==아이디 '아이디'입니다. 2개equals 그렇지는 않다==사용하는 것은 보통 잘못되어 있습니다.== 타입으로, 「」를 참조해 주세요.equals대신 사용해야 합니다.

, 어떤 의 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」equals 아니다==string을 사용하여new String(anotherString)컨스트럭터그러나, 이것은 매우 특이하고, 좀처럼 의도하지 않는다는 것을 다시 말할 필요가 있다.

레퍼런스

관련 문제

문자열 리터럴문자열 상수 풀에 들어갑니다.

아래 스냅샷은 시각적으로 이해하고 더 오래 기억할 수 있도록 도와줄 수 있습니다.

여기에 이미지 설명 입력


한 줄씩 개체 생성:

String str1 = new String("java5");

생성자에서 문자열 리터럴 "java5"를 사용하면 새 문자열 값이 문자열 상수 풀에 저장됩니다.새 연산자를 사용하면 "java5"를 값으로 하는 새 문자열 개체가 힙에 생성됩니다.

String str2 = "java5"

참조 "str2"가 문자열 상수 풀에 이미 저장된 값을 가리킵니다.

String str3 = new String(str2);

"str2"에 의해 참조와 동일한 값을 가진 새 문자열 개체가 힙에 생성됩니다.

String str4 = "java5";

참조 "str4"가 문자열 상수 풀에 이미 저장된 값을 가리킵니다.

총 객체: 힙 - 2, 풀 - 1

Oracle 커뮤니티에 대한 자세한 내용

문자열 상수 풀에 문자열을 만듭니다.

String s = "text";

풀에 ."text" 표준 문자열( 「」 「」 「」 「」 「」s 두 모두 의 .

String s = new String("text");

sGC로 하다

반면 문자열 리터럴은 재사용됩니다.「 」를 사용하고 "text"클래스의 여러 위치에서 실제로는 하나의 문자열(풀 내의 동일한 문자열에 대한 여러 참조)이 됩니다.

JLS

이 개념은 JLS에 의해 "interning"이라고 불립니다.

JLS 7 3.10.5로부터의 관련 패스워드:

또한 문자열 리터럴은 항상 클래스 String의 동일한 인스턴스를 참조합니다.이는 문자열 리터럴(또는 일반적으로는 상수 표현의 값인 문자열('15.28))이 String.intern 메서드를 사용하여 고유한 인스턴스를 공유하기 위해 "interned"되기 때문입니다.

예 3.10.5-1.문자열 리터럴

컴파일 유닛(77.3)으로 구성된 프로그램:

package testPackage;
class Test {
    public static void main(String[] args) {
        String hello = "Hello", lo = "lo";
        System.out.print((hello == "Hello") + " ");
        System.out.print((Other.hello == hello) + " ");
        System.out.print((other.Other.hello == hello) + " ");
        System.out.print((hello == ("Hel"+"lo")) + " ");
        System.out.print((hello == ("Hel"+lo)) + " ");
        System.out.println(hello == ("Hel"+lo).intern());
    }
}
class Other { static String hello = "Hello"; }

컴파일 유닛:

package other;
public class Other { public static String hello = "Hello"; }

는 다음과 같은 출력을 생성합니다.

true true true true false true

JVMS

JVMS 7 5.1의 특징:

문자열 리터럴은 클래스 String 인스턴스를 참조하는 것으로 클래스 또는 인터페이스의 바이너리 표현 중 CONST_String_info 구조('4.4.3)에서 파생됩니다.CONST_String_info 구조체는 문자열 리터럴을 구성하는 Unicode 코드 포인트의 시퀀스를 제공합니다.

Java 프로그래밍 언어에서는 동일한 문자열 리터럴(같은 코드포인트 시퀀스를 포함하는 리터럴)이 클래스 문자열의 동일한 인스턴스(JLS ls 3.10.5)를 참조해야 합니다.또한 String.intern 메서드가 임의의 문자열로 호출된 경우 그 문자열이 리터럴로 표시되었을 때 반환되는 동일한 클래스인스턴스에 대한 참조가 됩니다.따라서 다음 식에는 true 값을 지정해야 합니다.

("a" + "b" + "c").intern() == "abc"

문자열 리터럴을 도출하기 위해 Java Virtual Machine은 CONTANT_String_info 구조에 의해 지정된 코드 포인트의 시퀀스를 조사합니다.

  • 메서드 String.intern이 CONST_String_info 구조에 의해 지정된 것과 동일한 Unicode 코드 포인트 시퀀스를 포함하는 클래스 String 인스턴스에서 이전에 호출된 경우 문자열 리터럴 파생 결과는 클래스 String의 동일한 인스턴스를 참조합니다.

  • 그렇지 않으면 CONST_String_info 구조에 의해 지정된 Unicode 코드포인트 시퀀스를 포함하는 클래스 String의 새로운 인스턴스가 생성됩니다.이 클래스인스턴스에 대한 참조는 문자열 리터럴파생 결과입니다.마지막으로 새로운 String 인스턴스의 intern 메서드가 호출됩니다.

바이트 코드

OpenJDK 7에서의 바이트 코드 실장을 살펴보는 것도 도움이 됩니다.

디컴파일 할 경우:

public class StringPool {
    public static void main(String[] args) {
        String a = "abc";
        String b = "abc";
        String c = new String("abc");
        System.out.println(a);
        System.out.println(b);
        System.out.println(a == c);
    }
}

상수 풀에 있습니다.

#2 = String             #32   // abc
[...]
#32 = Utf8               abc

★★★★★★★★★★★★★★★★★」main:

 0: ldc           #2          // String abc
 2: astore_1
 3: ldc           #2          // String abc
 5: astore_2
 6: new           #3          // class java/lang/String
 9: dup
10: ldc           #2          // String abc
12: invokespecial #4          // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne     42
38: iconst_1
39: goto          43
42: iconst_0
43: invokevirtual #7          // Method java/io/PrintStream.println:(Z)V

주의:

  • 0 ★★★★★★★★★★★★★★★★★」3 : ★★★ldc #2이치노
  • 12를 사용합니다).#2argument(인수)로)
  • 35a ★★★★★★★★★★★★★★★★★」c 사물과 됩니다.if_acmpne

상수 문자열의 표현은 바이트 코드에서 매우 매직합니다.

  • 일반 개체와 달리 전용 CONTANT_String_info 구조를 가집니다(예:new String)
  • 구조체는 데이터를 포함하는 CONST_Utf8_info 구조를 가리킵니다.이것은 문자열을 나타내는 데 필요한 유일한 데이터입니다.

을 가리킬 가 Utf8에 의해 .ldc.

필드에 대해서도 비슷한 테스트를 실시했습니다.

  • static final String s = "abc"상수속성을 통해 상수 테이블을 가리킵니다.
  • 는 이러한 가지고 않지만 be종필필음음음음음음음음음음음음음음음음음 non non non non non non non non non non non non로 초기화할 수 .ldc

결론: 문자열 풀에 대한 직접 바이트 코드가 지원되며 메모리 표현은 효율적입니다.

보너스: 직접 바이트 코드를 지원하지 않는 Integer 풀과 비교합니다(즉, no).CONSTANT_String_info★★★★★★★★★★★★★★★★★★」

모든 String 리터럴은 문자열 리터럴 풀 내에 생성되며 풀에서는 중복을 허용하지 않습니다.따라서 동일한 리터럴 값으로 여러 문자열 개체가 초기화되면 모든 개체가 동일한 리터럴을 가리킵니다.

String obj1 = "abc";
String obj2 = "abc";

"obj1"과 "obj2"는 동일한 문자열 리터럴을 가리키며 문자열 리터럴 풀에는 "sublic" 리터럴이 1개만 있습니다.

새로운 키워드를 사용하여 String 클래스 개체를 만들면 생성된 문자열이 힙메모리에 저장됩니다.String 클래스 생성자에 매개 변수로 전달된 문자열 리터럴은 문자열 풀에 저장됩니다.새 연산자를 사용하여 동일한 값을 사용하여 여러 개체를 만들 경우 이 새 연산자를 사용하지 않도록 해야 하므로 매번 힙에 새 개체가 생성됩니다.

String obj1 = new String("abc");
String obj2 = new String("abc");

"obj1"과 "obj2"는 힙 내의 두 개의 다른 개체를 가리키며 문자열 리터럴 풀에는 하나의 리터럴만 있습니다.

또한 문자열의 동작에 관해 주의해야 할 점은 문자열에 대한 새로운 할당 또는 연결이 이루어지면 메모리에 새로운 개체가 생성된다는 것입니다.

String str1 = "abc";
String str2 = "abc" + "def";
str1 = "xyz";
str2 = str1 + "ghi";

의의: :
: 1 : """"abcabcabcabc::::::::::::::.
행 2: "abcdef" 리터럴은 문자열 풀에 저장됩니다.
행 3: 새로운 "xyz" 리터럴이 문자열 풀에 저장되고 "str1"이 이 리터럴을 가리키기 시작합니다.
줄 4: 다른 변수에 추가함으로써 값이 생성되므로 결과는 힙 메모리에 저장되고 "ghi"를 추가하는 리터럴은 문자열 풀에 존재하는지 확인되며 위의 경우 존재하지 않으므로 생성됩니다.

@Braj: 나는 당신이 반대로 언급했다고 생각한다.틀렸으면 정정해 주세요

한 줄씩 개체 생성:

String str1 = 새로운 String("java5")

   Pool- "java5" (1 Object)

   Heap - str1 => "java5" (1 Object)

String str2 = "timeout5"

  pool- str2 => "java5" (1 Object)

  heap - str1 => "java5" (1 Object)

String str3 = 새로운 String(str2)

  pool- str2 => "java5" (1 Object)

  heap- str1 => "java5", str3 => "java5" (2 Objects)

String str4 = "timeout5"

  pool - str2 => str4 => "java5" (1 Object)

  heap - str1 => "java5", str3 => "java5" (2 Objects)

"bla"의 이라는 것Strings.createString("bla")에서는 이렇게 .공장에는 이렇게 만들어진 모든 현이 있습니다.

이 값이 호출되면 이 값을 가진 문자열이 풀에 이미 있는지 확인합니다.true일 경우 이 문자열 개체를 반환하므로 이 방법으로 얻은 문자열은 실제로 동일한 개체입니다.

그렇지 않으면 내부에서 새 문자열 개체를 생성하여 풀에 저장한 후 반환합니다.따라서 다음 번에 같은 문자열 값을 조회할 때 동일한 인스턴스를 반환합니다.

" " "new String("")는 문자열 리터럴수영장을 바이패스하여 이 동작을 덮어씁니다.따라서 동등성은 항상 다음을 사용하여 확인해야 합니다.equals()오브젝트 참조 등호화 대신 문자 시퀀스를 비교합니다.

그 차이를 이해하기 위한 간단한 방법은 다음과 같습니다.

String s ="abc";
String s1= "abc";
String s2=new String("abc");

        if(s==s1){
            System.out.println("s==s1 is true");
        }else{
            System.out.println("s==s1 is false");
        }
        if(s==s2){
            System.out.println("s==s2 is true");
        }else{
            System.out.println("s==s2 is false");
        }

출력은

s==s1 is true
s==s2 is false

따라서 새로운 String()은 항상 새로운 인스턴스를 만듭니다.

프로그래머의 관점에서는 똑같아 보이지만 퍼포먼스에 큰 영향을 미칩니다.거의 항상 첫 번째 양식을 사용하는 것이 좋습니다.

String str = new String("hello")

문자열 상수 풀에 문자열 "hello"가 이미 포함되어 있는지 확인합니다.존재하는 경우 String 상수 풀에 엔트리는 추가되지 않습니다.존재하지 않는 경우 String 상수 풀에 엔트리가 추가됩니다.

됩니다.또한 " " " "str참조는 힙 메모리 위치에 생성된 개체를 가리킵니다.

str을 명시적으로 .str.intern();

String str = "world";

문자열 상수 풀에 문자열 "hello"가 이미 포함되어 있는지 확인합니다.존재하는 경우 String 상수 풀에 엔트리는 추가되지 않습니다.존재하지 않는 경우 String 상수 풀에 엔트리가 추가됩니다.

두 " " " 입니다.strString에 대한 - 에 대한 포인트"world"상수 풀에 표시됩니다.

String을 다음과 같이 저장하는 경우

String string1 = "Hello";

그런 다음 JVM은 String 상수 풀이라는 별도의 메모리 블록에 지정된 가격의 String 개체를 만듭니다.

그리고 우리가 다른 String을 만들고자 하는 경향이 있을 때마다

String string2 = "Hello";

JVM은 String 상수 풀 내에 가격이 일정한 String 개체가 존재하는지 여부를 확인합니다.이 경우 JVM은 기존 개체의 참조를 새 변수에 할당하지 않습니다.

String을 저장했을 때

String string = new String("Hello");

new 키워드를 사용하면 String 상수 풀의 내용에 관계없이 지정된 가격의 새로운 객체가 생성됩니다.

답변이 늦어서 죄송하지만 답변이 매우 필요했습니다.먼저 Java.lang을 알아야 합니다.String Class 규칙

  1. ★★★★★★★★★★★★★★★★★★★★★★String str="java";는 Object키워드 와String Object(String Object)(String Object(String Object)(큰따옴표만 사용).String str=new String("java");

  2. 문자열은 불변의 객체입니다.값이 변경되면 새 개체가 생성되어 사용자에게 반환됩니다( 참조).replace() and replaceAll()을 사용하다

  3. 이로 인해 수정 시 많은 String 객체의 문제가 발생하였고, 그래서 Java의 크리에이터들은 StringPool이라고 불리는 아이디어를 생각해냈습니다. Pool이라는 되는 힙 됩니다.스트링Char[](Java 9 이전 버전) 또는byte[](Java 9 이후 읽기 단축).

  4. 문자열 리터럴은 StringPool에 저장되며 String Objects는 일반적인 힙오브젝트 영역에 저장됩니다.

  5. 오브젝트 문자열 초기화 JVM 힙이 String Operations에서만 종료되는 경우 Java Development 팀은 String Pool에 대한 메모리 참조를 이동/변경하는 intern() 솔루션을 고안했습니다.

    프로그램:객체에 대한 문자열 참조 비교

java.lang을 이해하기 위한 또 다른 좋은 링크입니다.스트링 향상

import java.util.*; 

class GFG { 
    public static void main(String[] args) 
    { 
      String siteName1 = "java.com";
        String siteName2 = "java.com";
        String siteName3 = new String("java.com");
        String siteName4 = new String("java.com").intern();
      
    System.out.println("siteName1:::"+Integer.toHexString(System.identityHashCode(siteName1)));
      System.out.println("siteName2:::"+Integer.toHexString(System.identityHashCode(siteName2)));
      System.out.println("siteName3 creation Of New Object Without Interned:::"+Integer.toHexString(System.identityHashCode(siteName3)));//must be Diffrent bcoz new Object In Heap Area
      System.out.println("siteName4 creation Of New Object With Interned:::"+Integer.toHexString(System.identityHashCode(siteName4)));//must be same MemoryAddress of siteName1,siteName2 and Interned, bcoz Objects Points to String pool Now
      
      System.out.println(siteName1 == siteName2); // true
      System.out.println(siteName1 == siteName3); // false this tells about lietral vs String Objects
      String siteName5 = siteName3.intern(); // Interning will not change Original Object but gives us a new Object
      
      System.out.println("siteName5 Interned from siteName3:::"+Integer.toHexString(System.identityHashCode(siteName5)));//must be same MemoryAddress of siteName1,siteName2 and Interned, bcoz Objects Points to String pool Now
      
      System.out.println(siteName1 == siteName3); // false this tells about Immutability
      System.out.println(siteName1 == siteName5); // true After Intering both are same
      System.out.println(siteName1 == siteName4); // true
      System.out.println(siteName5 == siteName4); // true
    } 
}

언급URL : https://stackoverflow.com/questions/3052442/what-is-the-difference-between-text-and-new-stringtext

반응형