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


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.5 및 JVMS §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.