""를 사용하여 문자열을 초기화하는 방법은 무엇입니까?


154

String이 다른 클래스와 같은 클래스라면 큰 따옴표를 사용하여 어떻게 초기화 할 수 있습니까?


25
문자열은 VIP 클래스입니다. " "이미 문자열입니다!
johnchen902

2
특별한 의미가 없습니다. 방금 매우 중요 했어 즉 java.lang.String, Java 언어를 특별히 취급하십시오.
johnchen902

16
누가 그 끈이 "다른 것과 같은 클래스"라고 말합니까? 다른 수업과 달리 매우 특별한 수업입니다. 당신의 가정이 거짓이기 때문에, 그 질문은 실제로 대답 할 수 없습니다.
Eric Lippert

5
가정이 거짓이기 때문에 질문에 대답 할 수 없다는 의미는 아닙니다. 정답은 이미 197 표입니다.
Koray Tugay

답변:


293

자바 문자열은 특별하다

Java 설계자는 언어의 성능을 향상시키기 위해 모든 것을 객체로 만드는 대신 객체 지향 언어로 기본 유형을 유지하기로 결정했습니다. 프리미티브는 콜 스택에 저장되므로 스토리지 공간이 적고 조작하기가 저렴합니다. 반면에 객체는 프로그램 힙에 저장되므로 복잡한 메모리 관리 및 더 많은 저장 공간이 필요합니다.

성능상의 이유로 Java의 문자열은 기본과 클래스 사이에 있도록 설계되었습니다.

예를 들어

String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object

여기에 이미지 설명을 입력하십시오

참고 : 문자열 리터럴 은 공통 풀에 저장됩니다. 이것은 동일한 내용을 가진 문자열을위한 스토리지 공유를 용이하게하여 스토리지를 보존합니다. Stringnew 연산자를 통해 할당 된 객체는에 저장되며 heap동일한 콘텐츠에 대한 스토리지 공유가 없습니다.


72
"공통 풀"은 일반적으로 힙의 일부입니다.
Joachim Sauer

3
@JoachimSauer 예. 약간의 이점이 있습니다 :) 메모에 추가했습니다. 기억해 주셔서 감사합니다.
Suresh Atta

2
따라서 String s1 = "Hello"를 작성하는 것이 더 빠릅니다. String보다 s2 = new String ( "Hello") ;?
user2097804

28
귀하의 예에서 s1 == s2 == s3이지만 s4! = s5
Alfredo Osorio

8
최근 핫스팟 jvm의 @AndrewJanke (7), 문자열 풀은 perm gen에 없으며 Java 8
부터는

50

Java는 String을 특수 클래스로 취급하므로 두 가지 방법으로 초기화 할 수 있습니다

  1. 직접 리터럴 할당

    String a = "adsasdf";
  2. 새 키워드를 사용하는 다른 개체로

    String a = new String("adsasdf");

==부호 와 비교하려면 특별한주의가 필요합니다 .

String a = "asdf";
String b = "asdf";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True

String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b);  // False
System.out.println(a.equals(b)); // True

첫 번째 경우에는 객체 a와 b가 호출 된 것으로 유지되고 literal pool둘 다 동일한 객체를 참조하므로 두 방식이 동일하기 때문입니다.

그러나 두 번째 경우 a와 b는 다른 객체를 초기화 할 때와 같이 다른 객체를 참조합니다. 따라서 ==연산자 와 비교할 때 값이 같지 않지만 값이 같습니다.


18

문자열은 JLS에서 특별한 처리를 얻습니다. 리터럴이 존재하는 두 가지 비 기본 유형 중 하나입니다 (다른 하나는 Class) * .

에서 JLS :

문자열 리터럴은`String [...] 클래스의 인스턴스에 대한 참조입니다.

* 음, "null literal "을 가진 "null type"도null 있지만 대부분의 사람들은 "null type"을 적절한 유형으로 생각하지 않습니다.


1
또한 "널 유형"이 Java에서 올바른 유형이라는 것을 알지 못했습니다. 유용한 정보이므로 글꼴 크기를 늘려야합니다.
Grijesh Chauhan

1
@GrijeshChauhan : 음, "널 타입"은 null참조 타입 변수에 할당 할 수있는 멋진 표현 입니다. 그렇지 않으면 흥미로운 유형이 아닙니다.
Joachim Sauer

15

Java 언어의 기능입니다. 소스 코드의 문자열 리터럴에는 특별한 처리가 제공됩니다.

언어 사양은, 여기 , 단순히 문자열 리터럴의 것을 말한다 String유형


5

큰 따옴표 안의 텍스트는 리터럴 String객체를 만듭니다 .

String myString = "Some text";

위의 코드는 String큰 따옴표를 사용하여 객체를 만듭니다 .


4

문자열은 프로그래밍 언어에서 매우 자주 사용됩니다. java는 객체 지향이므로 문자열은 객체입니다. 번거로운 새 String ( "someString"); 문자열 객체가 필요할 때마다 statement java를 사용하면 문자열 리터럴을 사용하여 문자열 객체를 만들 수 있습니다.

그러나 문자열 평등을 명심해야합니다. 여기에 내가 의미하는 바를 보여주는 짧은 JUnit 테스트가 있습니다.

    @Test
    public void stringTest() {
       // a string literal and a string object created 
       // with the same literal are equal
       assertEquals("string", new String("string"));

       // two string literals are the same string object
       assertSame("string", "string"); 

       // a string literal is not the same object instance 
       // as a string object created with the same string literal
       assertFalse("string" == new String("string"));

       // java's String.intern() method gives you the same
       // string object reference for all strings that are equal.
       assertSame("string", new String("string").intern());
    }

로만 문자열을 초기화 할 수 있다면 new String(String src)생성자에게 문자열 리터럴을 제공 할 수도 없습니다. 을 초기화 한 char []다음 String(char [] src)생성자 를 사용 하여 문자열을 구성하거나 파일에서 문자열을 읽어야합니다.
AJMansfield

맞지 않습니다. 문자열 리터럴은 소스 파일에서 큰 따옴표로 묶인 문자 시퀀스입니다. Java는이 리터럴을 사용하여 문자열 인스턴스를 자동으로 작성합니다. 따라서 리터럴과 String 객체는 동일하지만 동일하지 않습니다. 새로운 String ( "")을 사용해야하는 방식으로 Java를 구현할 수도 있습니다. String 객체를 인스턴스화하지만 인생을 더 힘들게 만듭니다. 따라서 새 String ( "a string")을 작성할 때 java는 리터럴 "문자열"에 대한 문자열 객체를 작성하고이 문자열 객체를 새 문자열의 구성 자로 전달합니다.
René Link

2

그냥 언급하면됩니다. 문자열 리터럴은 다음과 같은 코드를 작성할 수있는 String 클래스의 인스턴스에 대한 참조입니다.

 "abc".getBytes ();

 "a : b : c".split ( ":");

 "愛".codePointAt (0);

2

- 문자열의 클래스입니다 자바 . 당신은 그것에 대해 옳았으므로 항상 new키워드로 초기화 할 수 있습니다 .

- 하지만 우리가 뭔가를 할 때 :

String s = "";

위의 문은으로 표시됩니다 컴파일러특별 String 객체 다음 및 로드하는 동안 JVM을 , (로딩이 초기화되기 전에 완료) 클래스의로 알려진이보고 문자열 리터럴 A의 저장, 문자열 리터럴 풀을 .

- 문자열을 사용하여 생성 할 수 있도록 new()하고,에 의해 ""방법,하지만 그것은 문자열 리터럴 풀에서 참조를 가지고 있기 때문에 후자는, 그 문자열 객체에 대한 참조가 없어도 힙에서 숙박 문자열 리터럴을 제공합니다.


2

Java는 2 단계 프로세스를 수행합니다.

String str = "hello";

에 해당

char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);

[.NET] [1]과 비슷한 것이 있습니다.

String(Char[]) constructor

않습니다

String(char[] value)

참조 추가 :-


2
설명하는 프로세스는 Java가 실제로하는 작업이 아닙니다. 다른 사람들이 이미 언급했듯이 "hello"문자열 리터럴이며 컴파일러가 상수 풀에 넣을 것 입니다. JLS §3.10.5JVMS §5.1을 참조하십시오 .
siegi

1

Java.lang.String수업이 아닙니다. 핵심 언어의 핵심 부분입니다. 컴파일러에는 구문 설탕이 있습니다. 예를 들어 ""의 약어와 같습니다 new String(""). 작성하면 ""컴파일러는 공간을 절약하기 위해 동일한 인스턴스에 동일한 문자열을 최적화합니다."a" + 5 == "a5" ==> true

컴파일러는 객체 버전과 기본 유형 사이에서 상자 / 상자를 풀지 않아도되는 것을 포함하여 많은 것을위한 구문 설탕을 가지고 있습니다. 부모는 Object, 기본 생성자를 의미하지 않습니다 ...


5
""의 약어가 아닙니다 new String(""). 를 사용하는 ""경우 가장 먼저 수행 할 작업은 JVM의 문자열 풀에서 일치 항목을 찾는 것입니다.이 경우 true이면 해당 문자열을 리턴합니다. 을 사용 new String("")하면 문자열 자체가 이미 문자열 풀에 존재하더라도 문자열을 항상 새로 작성합니다 (문자열 풀에 저장되지 않기 때문에).
g00glen00b

내 답변을 업데이트했습니다. 사람들은 이것을 Lisp 심볼 유형과 같은 문자열 상수를 사용하는 것과 같이 유리하게 사용합니까?
Sylwester
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.