Programing

문자열 객체와 문자열 리터럴의 차이점

lottogame 2020. 4. 12. 10:12
반응형

문자열 객체와 문자열 리터럴의 차이점


이 질문에는 이미 답변이 있습니다.

차이점은 무엇입니까

String str = new String("abc");

String str = "abc";

당신이 사용하는 경우 문자열 리터럴 문자열이 될 수 구금 ,하지만 당신은 사용할 때 new String("...")새 문자열 개체를 가져옵니다.

이 예제에서 두 문자열 리터럴은 동일한 객체를 참조합니다.

String a = "abc"; 
String b = "abc";
System.out.println(a == b);  // true

여기에 2 개의 서로 다른 객체가 만들어지고 다른 참조가 있습니다.

String c = new String("abc");
String d = new String("abc");
System.out.println(c == d);  // false

일반적으로 가능하면 문자열 리터럴 표기법을 사용해야합니다. 읽기 쉽고 컴파일러가 코드 최적화 할 수 있는 기회를 제공 합니다.


문자열 리터럴 자바 언어 개념이다. 이것은 문자열 리터럴입니다.

"a String literal"

문자열 객체 의 개별 인스턴스 java.lang.String클래스입니다.

String s1 = "abcde";
String s2 = new String("abcde");
String s3 = "abcde";

모두 유효하지만 약간의 차이가 있습니다. 내부 문자열 객체를 s1참조 합니다. 이는 문자 순서 가 중앙 위치에 저장되고 동일한 리터럴 이 다시 사용될 때마다 JVM이 새 문자열 오브젝트를 작성하지 않고 캐시 된 문자열 의 참조를 사용함을 의미합니다 ."abcde""abcde"

s2새로운 String 객체 로 보장 되므로이 경우에는 다음과 같습니다.

s1 == s2 // is false
s1 == s3 // is true
s1.equals(s2) // is true

긴 답변은 여기 에서 확인할 수 있으므로 짧은 답변을 드리겠습니다.

이렇게하면 :

String str = "abc";

String 에서 intern()메소드를 호출하고 있습니다. 이 방법 은 내부 객체 참조 합니다. 호출 한 문자열이 이미 풀에 있으면 해당 참조 가에 할당됩니다 . 그렇지 않은 경우 새 풀에 배치되고 이에 대한 참조가에 할당됩니다 .Stringintern()StringstrStringstr

다음 코드가 주어진다 :

String str = "abc";
String str2 = "abc";
boolean identity = str == str2;

당신이 수행하여 개체의 신원을 확인하는 경우 ==(당신이 말 그대로 요구하고있다 :이 두 참조가 동일한 개체를 가리 할), 당신은 얻을 true.

그러나, 당신은하지 않습니다 필요intern() Strings. 다음 Object을 수행하여 힙에 새로 작성하도록 할 수 있습니다 .

String str = new String("abc");
String str2 = new String("abc");
boolean identity = str == str2;

이 경우, str그리고 str2다른에 대한 참조 Objects된 어느 것도, 구금 당신이 테스트 할 때 그래서, Object사용 정체성 ==, 당신이 얻을 것이다은 false.

실제로 코딩 좋은 측면에서 : 할 수 없습니다 사용하는 ==문자열 어떤지를 확인하기 위해 사용하는 .equals()대신.


문자열을 변경할 수 없으므로 다음을 수행하십시오.

String a = "xyz"

문자열을 만드는 동안, 스트링의 풀에서 JVM 검색 이미 문자열 값이 존재하는 경우 "xyz"만약 그렇다면, 'a'단순히 해당 문자열의 참조가 될 것이며, 새로운 String 객체가 만들어지지 않습니다.

그러나 당신이 말한다면 :

String a = new String("xyz")

풀에있는 String경우에도 JVM이 새 참조 를 작성하도록 "xyz"합니다.

자세한 내용은 이것을 읽으십시오 .


"abc" 리터럴 문자열입니다.

Java에서 이러한 리터럴 문자열은 내부적으로 풀링 "abc"되며 코드에서 선언 된 해당 문자열 리터럴이있는 경우 동일한 String 인스턴스 가 사용됩니다. "abc" == "abc"둘 다 동일한 String 인스턴스 이므로 항상 사실입니다.

String.intern()방법을 사용하면 내부적으로 풀링 된 문자열에 원하는 문자열을 추가 할 수 있습니다.이 문자열은 java가 종료 될 때까지 메모리에 보관됩니다.

반면에를 사용 new String("abc")하면 논리적으로 "abc"리터럴 과 동일한 새 문자열 객체가 메모리에 생성됩니다 . "abc" == new String("abc")논리적으로 동일하지만 서로 다른 인스턴스를 참조하는 것처럼 항상 거짓입니다.

문자열 리터럴 주위에 문자열 생성자를 감싸는 것은 가치가 없으며 필요한 것보다 더 많은 메모리를 불필요하게 사용합니다.


문자열은 다른 프로그래밍 언어와 다른 Java 클래스입니다. 모든 클래스에서 객체 선언과 초기화는

String st1 = new String();

또는

String st2 = new String("Hello"); 
String st3 = new String("Hello");

여기에 st1, st2그리고 st3다른 개체입니다.

그건:

st1 == st2 // false
st1 == st3 // false
st2 == st3 // false

왜냐하면 st1, st2, st33 명 가지 목적 및 참조하는 ==메모리 위치에 평등, 따라서 결과를 확인한다.

그러나:

st1.equals(st2) // false
st2.equals(st3) // true

이곳까지 .equals()콘텐츠에 대한 검사 방법 및 내용 st1 = "", st2 = "hello"st3 = "hello". 따라서 결과.

그리고 String 선언의 경우

String st = "hello";

여기서 클래스의 intern()메소드 String가 호출 "hello"되어 인턴 풀에 있는지 확인 하고, 그렇지 않은 경우 인턴 풀에 추가되고 "hello"가 인턴 풀에 존재 st하면 기존의 메모리를 가리 킵니다 "hello".

따라서 다음의 경우 :

String st3 = "hello";
String st4 = "hello"; 

여기:

st3 == st4 // true

때문에 st3st4같은 메모리 주소를 가리키는.

또한:

st3.equals(st4);  // true as usual

첫 번째 경우에는 두 개의 객체가 생성됩니다.

두 번째 경우는 단지 하나입니다.

두 가지 방법 모두 str를 언급 하지만 "abc".


일부 분해는 항상 흥미 롭습니다 ...

$ cat Test.java 
public class Test {
    public static void main(String... args) {
        String abc = "abc";
        String def = new String("def");
    }
}

$ javap -c -v Test
Compiled from "Test.java"
public class Test extends java.lang.Object
  SourceFile: "Test.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method  #7.#16;  //  java/lang/Object."<init>":()V
const #2 = String  #17;     //  abc
const #3 = class   #18;     //  java/lang/String
const #4 = String  #19;     //  def
const #5 = Method  #3.#20;  //  java/lang/String."<init>":(Ljava/lang/String;)V
const #6 = class   #21;     //  Test
const #7 = class   #22;     //  java/lang/Object
const #8 = Asciz   <init>;
...

{
public Test(); ...    

public static void main(java.lang.String[]);
  Code:
   Stack=3, Locals=3, Args_size=1
    0:    ldc #2;           // Load string constant "abc"
    2:    astore_1          // Store top of stack onto local variable 1
    3:    new #3;           // class java/lang/String
    6:    dup               // duplicate top of stack
    7:    ldc #4;           // Load string constant "def"
    9:    invokespecial #5; // Invoke constructor
   12:    astore_2          // Store top of stack onto local variable 2
   13:    return
}

이미 게시 된 답변 외에도 javaranch에 대한 훌륭한 기사를 참조하십시오 .


String 클래스 문서 에 따르면 동일합니다.

에 대한 설명서 String(String original): 또한이 말한다 원래의 명시적인 카피가 필요하지 않은 문자열은 불변이므로,이 생성자의 사용이 불필요합니다.

Java 문서가 오도하는 것처럼 보이기 때문에 다른 응답을 찾으십시오.


다음은 몇 가지 비교입니다.

String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");

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

System.out.println(s1 == s3);   //false
System.out.println(s1.equals(s3)); //true

s3 = s3.intern();
System.out.println(s1 == s3); //true
System.out.println(s1.equals(s3)); //true

intern()호출되는 기준이 변경됩니다.


String 객체와 문자열 리터럴 사이에는 미묘한 차이가 있습니다.

String s = "abc"; // creates one String object and one reference variable

이 간단한 경우 " abc "는 풀에 들어가고 s 는이를 참조합니다.

String s = new String("abc"); // creates two objects,and one reference variable

이 경우 new키워드를 사용했기 때문에 Java는 일반 (풀이 아닌) 메모리에 새 String 객체를 만들고 s에서 참조합니다. 또한 리터럴 " abc "가 풀에 배치됩니다.


String s = new String("FFFF")"FFFF"문자열 String을 가리키는 문자열과 객체라는 2 개의 객체를 만듭니다. "FFFF"따라서 포인터에 대한 포인터와 같습니다 (참조에 대한 언급, 용어에 관심이 없습니다).

절대 사용해서는 안된다고합니다 new String("FFFF")

참고 URL : https://stackoverflow.com/questions/3297867/difference-between-string-object-and-string-literal


반응형