Java에 String.Empty가없는 이유는 무엇입니까?


260

문자열 리터럴을 입력 할 때마다 ""문자열 풀에서 동일한 String 객체가 참조 된다는 것을 이해합니다 .

그러나 String API에 왜을 포함하지 않으므로에 대한 public static final String Empty = "";참조를 사용할 수 String.Empty있습니까?

컴파일러는 기존 문자열을 참조하고 이미 재사용을 위해 이미 생성되었는지 확인할 필요가 없으므로 컴파일 시간을 절약 할 수 있습니다. 그리고 개인적으로 문자열 리터럴, 특히 작은 것의 확산은 많은 경우 "코드 냄새"라고 생각합니다.

String.Empty 뒤에 그랜드 디자인 이유가 있었습니까? 아니면 언어 작성자가 단순히 내 견해를 공유하지 않았습니까?


5
Aidanc : 나는 그가 당신이 좋아하는 물건을 할 상황을 의미한다고 생각 outputBlah = "", 그는 아마 선호 something == String.Empty이상 something.Length > 0뿐만 아니라 (당신은 널 (null) 검사를 건너 뛰십시오.)
Skurmedel

2
@Aidanc-그는 문자열 "emptiness"를 확인하는 함수가 아닌 Collections.EMPTY_SET 과 같은 "빈 멤버"를 찾고있었습니다 .
Tim Stone

2
@Aidanc : 이것이 실제로 영감을 준 것은 'TextBox.setText ( "");'입니다.
Tom Tresansky

3
있다 String.isEmpty()기능 ... 왜 당신이 원하는 것 String.EMPTY?
Buhake Sindi

8
String.isEmpty()빈 문자열을 반환하지 않습니다.
Steve Kuo

답변:


191

String.EMPTY12 자이고 ""2 자이며 둘 다 런타임시 메모리에서 정확히 동일한 인스턴스를 참조합니다. 왜 String.EMPTY컴파일 시간을 절약 할 수 있을지 잘 모르겠습니다 . 실제로 후자라고 생각합니다.

특히 고려 String의는 불변, 당신이 먼저 빈 문자열을 얻고, 거기에 몇 가지 작업을 수행 할 수 있습니다처럼 아니에요 - 최고의을 사용하는 StringBuilder(또는 StringBuffer과 문자열로 그 차례는 스레드 안전 할 경우).


의견에서 질문으로 업데이트 :

이것이 실제로 영감을 준 것은 TextBox.setText("");

적절한 수업에 상수를 제공하는 것이 합법적이라고 생각합니다.

private static final String EMPTY_STRING = "";

그런 다음 코드에서와 같이

TextBox.setText(EMPTY_STRING);

이런 식으로 IDE 또는 기타 비슷한 문자열을 채우는 것을 잊어 버린 것보다 빈 문자열을 원한다는 것이 분명합니다.


14
나는 여전히 당신을 +1 할 것이지만, 당신 StringBuilder이 열 중 아홉 번 StringBuilder이 연결보다는 사용 하기가 완전히 부적절하다고 언급 하지 않았기 때문에 더러워 집니다.
Randolpho

85
나는 더 명확하기 때문에 string.empty를 선호하는 경향이 있습니다. 또한 ""와 " '"과 같은 것을 시각적으로 구별하기 어려운 속도 상황이 있습니다. 결국 다른 사람들이 지적했듯이, 그것은 우리가 실제 일에 지루할 때 논쟁하도록 우리에게 사료를주는 무의미한 스타일 중 하나 일뿐입니다. =)
JohnFx

@Nodel M : 컴파일 시간과 관련하여, 동일한 문자열 값을 가진 2 개의 서로 다른 소스 파일에 2 개의 문자열 리터럴이 정의되어 있으면 컴파일러가 2 번째 파일에 도달 할 때 " 이 문자열에 대해 이미 알고 있습니다. " Java 컴파일러에 대한 전문가는 없지만 분명히 어떻게 될 수 있습니까? 그리고 그 검사를 건너 뛰면 컴파일 시간이 약간 향상 될 것이라고 생각합니다.
Tom Tresansky

@Tom-String interning은 컴파일 타임이 아닌 런타임에 수행된다고 생각하므로 실제로 다른 파일에서 빈 문자열을 상수로 사용하는 경우 컴파일러는 해당 클래스를 참조하여 String 리터럴로 해석해야합니다.
Noel M

1
@ Randolpho 문자열 연결을 사용할 때 실제로 후드 아래에서 StringBuilder를 사용하고 있습니다.
위스키시에

133

사용하다 org.apache.commons.lang.StringUtils.EMPTY


30
빈 ""보다 훨씬 좋고 읽기 쉽습니다. 나만이 아니라
Lakatos Gyula

2
@LakatosGyula-나는 당신일지도 모른다고 생각합니다. 능숙 자바 프로그래머는 아무런 문제가 읽기 없었다 ""... 그리고 대부분의 아마의 사용에 대해 큰 소리로 반대 것 EMPTY특정 상황을 제외하고 EMPTY도메인 특정 의미를 가지고있다. (그리고 그러한 경우에는 아마도 더 적절한 이름이있을 것입니다.)
Stephen C

14
@LakatosGyula 그것은 당신 만이 아닙니다. Java에서 .NET 개발로 갔고 String.Empty는 프레임 워크에서 기뻤습니다. 나는 빈 따옴표 세트보다 명확한 특성을 좋아합니다.
yohohoho

64
@StephenC 빈 ""을 볼 때 첫 번째 것은 버그, 누군가가 함수 등을 끝내지 않았다는 점을 떠올리게합니다. String.EMPTY를 사용하면 개발자가 빈 문자열을 반환하려고한다는 것을 정확히 알고 있습니다.
Lakatos Gyula

1
linter가 "blah blah blah 대신 명명 된 상수를 사용하십시오"라고 말할 때에도 도움이됩니다. 모든 프로그래머는 ""이 마술이 아니라는 것을 알고 있지만 고객에게 설명하지 않아도됩니다.
LizH

28

null 값에 대해 걱정하지 않고 빈 문자열과 비교하려면 다음을 수행하십시오.

if ("".equals(text))

궁극적으로 당신은 당신이 믿는 것을 가장 분명하게해야합니다. 대부분의 프로그래머는 ""는 빈 문자열을 의미하며 누군가가 입력하지 않은 문자열을 의미한다고 가정합니다.

성능 이점이 있다고 생각되면 테스트해야합니다. 자신의 테스트 가치가 없다고 생각한다면 실제로 가치가 없다는 좋은 증거입니다.

15 년 전에 언어가 설계되었을 때 해결 된 문제를 해결하려고하는 것 같습니다.


1
나는 파티에 상당히 늦었지만 Java 문자열은 변경할 수 없기 때문에 JVM 내의 모든 빈 문자열은 동일한 String 객체에 대한 다른 참조 일 뿐이라고 생각합니다. 따라서 다음 사항도 정확합니다. if ("" == text)
Ajoy Bhatia

12
@AjoyBhatia 문제는 새로운 빈 문자열을 만들 수 있다는 것입니다. if ("" == new String())거짓입니다. 더 나은 테스트if(text.isEmpty())
Peter Lawrey

1
@AjoyBhatia-문자열이 삽입 된 경우에만 해당됩니다. stackoverflow.com/questions/10578984/what-is-string-interning
Davor

9

실제로 String.EMPTY 상수를 원하면 프로젝트에서 "Constants"라는 유틸리티 정적 최종 클래스를 만들 수 있습니다. 이 클래스는 빈 문자열을 포함하여 상수를 유지합니다.

같은 생각으로 Integer 클래스에는 존재하지 않는 ZERO, ONE int 상수를 만들 수 있지만, 내가 언급했듯이 쓰기와 읽기가 어려울 것입니다.

for(int i=Constants.ZERO; ...) {
    if(myArray.length > Constants.ONE) {
        System.out.println("More than one element");
    }
}

기타.


8

Apache StringUtils도이 문제를 해결합니다.

다른 옵션의 실패 :

  • isEmpty ()-null 안전하지 않습니다. 문자열이 null이면 NPE를 throw합니다.
  • length () == 0-다시 null 안전하지 않습니다. 공백 문자열도 고려하지 않습니다.
  • EMPTY 상수와의 비교-null 안전하지 않을 수 있습니다. 공백 문제

Granted StringUtils는 드래그하는 또 다른 라이브러리이지만 잘 작동하고 많은 시간을 절약하고 Null을 확인하거나 NPE를 정상적으로 처리하는 번거 로움을 덜어줍니다.


3
그래서 ... 유일한 안전 옵션은 끔찍한 요다 조건입니다 보인다 "".equals(s)?
Lie Ryan

8

"문자열의 메모리 풀은 리터럴 형태로 재사용되며 대소 ​​문자는 닫힙니다"라고 말하지 마십시오. 컴파일러가 후드 아래에서하는 일은 여기가 아닙니다. 이 질문은 합리적으로 이루어졌으며 특히받은 많은 투표권이 주어졌습니다.

그것은 API에 대한 인간의 사용이 어렵 기 때문에 대칭 에 관한 것 입니다. 초기 Java SDK는이 규칙을 무시한 것으로 악명 높았지만 이제는 너무 늦었습니다. 내 머리 위에 몇 가지 예가 있습니다. "좋아하는"예를 자유롭게 들으십시오.

  • BigDecimal.ZERO이지만 AbstractCollection.EMPTY, String.EMPTY는 없습니다.
  • Array.length이지만 List.size ()
  • List.add (), Set.add ()이지만 Map.put (), ByteBuffer.put () 및 StringBuilder.append (), Stack.push ()를 잊지 말자

List 매개 변수 length ()라는 이름을 지정하더라도 메서드이므로 괄호가 여전히 필요합니다. Array.length는 공개 최종 변수이며, 배열은 변경할 수 없기 때문에 작동합니다. 따라서 여전히 Array.length 및 List.length ()가 있습니다. 더 혼란스럽고 오류가 발생하기 쉽다고 주장합니다. .append () 및 .push ()는 비슷한 작업을 수행하는 동안 적절하게 명명 된 것으로 생각합니다. 문자열을 추가하는 것은 정확히 당신이하고있는 일이지만 스택을 "추가"하지 않고 값을 밀어 넣습니다. 그리고 StringBuilder.push ()는 StringBuilder.pop ()을 의미하며 불가능합니다.
Craig Parton

템플릿 / 제네릭에서 제공되는 일관된 인터페이스는 알고리즘에도 도움이됩니다. 알고리즘에 컬렉션 길이가 필요한 경우 length (T) 또는 T.length () 만 있으면됩니다. 마찬가지로 스택, 목록 또는 문자열의 끝에 추가는 범용 add () 또는 append ()로 수행 할 수 있습니다. Java의 배열은 길이 속성이 노출 된 불변 / 내장 유형이라고 언급했습니다. 괜찮습니다. 컴파일러가 length (T) 또는 T.length ()에 대한 코드를 처리하거나 생성 할 수 없다는 의미는 아닙니다. 코 틀린은 다양한 경우에 대해 여러 가지 고유 한 방법을 생성합니다.
Slawomir

그러나 일관되게 이름이 지정된 length () 메소드는 길이를 확인할 수 있습니다. 그게 얼마나 유용한가요? 인터페이스를 통해 어떤 방식 으로든 사용할 수 있도록 목록과 배열을 추상화하는 것이 목표라면 데이터를 읽거나 쓰는 일관된 방법이 필요합니다. 이제 get (), set () 및 add () 메소드를 생성해야합니다. 기본적으로 어레이의 기능이 적은 목록보기를 작성합니다. Arrays.asList ()를 사용할 수 있고, 사용하기 쉽고, 가벼우므로 왜 휠을 재발 명해야합니까? 배열, 목록, StringBuilders 및 스택은 모두 특정 용도로 사용됩니다. 가장 잘 맞도록 인터페이스를 디자인하는 것이 더 좋습니다.
Craig Parton

5

모든 ""리터럴은 동일한 객체입니다. 왜 그렇게 복잡해 지나요? 타이핑하는 것이 길고 명확하지 않습니다 (컴파일러 비용은 최소입니다). Java의 문자열은 변경 불가능한 객체이므로 효율성을 제외하고는 구분할 필요가 없지만 빈 문자열 리터럴을 사용하면 크게 중요하지 않습니다.

정말로 EmptyString상수를 원한다면 스스로 만드십시오. 그러나 더 많은 코드를 장려하기 만하면됩니다. 그렇게 하면 아무런 이점 이 없습니다 .


27
x = String.Empty보다 더 의도를 전달합니다 x = "". 후자는 실수로 누락 될 수 있습니다. 이점이 전혀 없다고 말하는 것은 잘못된 것입니다.
Jeffrey L Whitledge

@ Jeffrey : 나는 특히 동의한다고 생각하지 않습니다. 내가 생각하는 어렵고 빠른 규칙이없는 곳 중 하나입니다.
Donal Fellows

예, Java 컴파일러는 문자열 풀에서 새 인스턴스를 작성하기 전에 문자열 리터럴이 이미 존재하는지 확인하는 것이 중요합니다.
rds

1
@Jeffrey-이것이 매우 오래되고 주관적인 토론이라는 것을 알고 있습니다. x = String.Empty의도를 전달합니다. 그러나 언어가 상수를 제공한다고 가정하면 String.Empty, x = ""그러한 상수가없는 것처럼 의도에 대해 정확히 알고 있습니다. 빈 문자열이 의도 된 세계 Java 코드의 모든 위치가 ""언급 한 정보를 얻기 위해 사용하지 않는다는 보장이 필요합니다 . 아이러니하게도 C #은 상수를 사용하고 사용을 장려하므로 말했듯이 그것이 매우 반대 의견이 많은 것으로 알고 있습니다.
chiccodoro

@chiccodoro-그렇습니다. 그래서 빈 문자열 리터럴 ""은 사고를 배제하기 위해 불법이어야합니다. 농담이야!
Jeffrey L Whitledge


3

String 리터럴 ""을 입력 할 때마다 동일한 String 객체가 String 풀에서 참조됨을 이해합니다.
그러한 보증은 없습니다. 그리고 당신은 당신의 응용 프로그램에서 그것에 의존 할 수 없으며, 결정하는 것은 완전히 jvm에 달려 있습니다.

아니면 언어 제작자가 단순히 내 의견을 공유하지 않았습니까?
네. 나에게는 우선 순위가 매우 낮은 것 같습니다.


6
JLS 그러한 보증을 하지 않습니다 .
Tim Stone

@Tim 당신이 '인턴'전화를하지 않는 한 아닙니다. 프로그래밍 방식으로 동일한 두 개의 큰 문자열을 구성하고 확인하는 것은 쉽습니다.
Nikita Rybak

@Tim 예를 들어 + = "a"를 반복 합니다. 100 번, b 와 동일하게 수행 하고 확인하십시오.
Nikita Rybak

5
맞습니다.하지만 설명 한 것은 문자열 리터럴이 아니며 컴파일 타임에 결과를 보장 할 수있는 표현식 (예 :)이 아닙니다 String username = "Bob" + " " + "Smith";. 프로그래밍 방식으로 작성된 문자열은 명시 적으로 intern()언급 한대로 명시 적으로 호출하지 않는 한 인턴 될 것이라는 보장이 없습니다 . OP의 시나리오 ""는 코드 전체에 빈 문자열 리터럴 을 사용하는 것을 설명 합니다. 자동 인터 닝이 발생하는 경우입니다.
Tim Stone

@ 팀 String a = ""; for(int i = 0; i < 100; i++) {a += "a";} String b = ""; for(int i = 0; i < 100; i++) {b += "b";} a.intern(); b.intern();지금 ab포인트 PermGen에 동일한 메모리 위치. 참고 이 문서
1ac0

1

늦은 답변이지만이 주제에 새로운 것을 추가한다고 생각합니다.

이전 답변 중 어느 것도 원래 질문에 대답하지 않았습니다. 일부는 상수 부족을 정당화하려고 시도했지만 다른 일부는 상수 부족을 처리 할 수있는 방법을 보여주었습니다. 그러나 어느 누구도 상수의 이점에 대해 설득력있는 타당성을 제공하지 않았으므로 그 부족한 부분이 여전히 제대로 설명되지 않았습니다.

상수는 특정 코드 오류가 눈에 띄지 않게하기 때문에 유용합니다.

""에 대한 수백 개의 참조가있는 큰 코드 기반이 있다고 가정하십시오. 누군가 코드를 스크롤하면서이 중 하나를 수정하고 ""로 변경합니다. 그러한 변화는 생산에 눈에 띄지 않을 가능성이 높으며,이 시점에서 출처를 알아 내기 어려운 일부 문제가 발생할 수 있습니다.

EMPTY라는 라이브러리 상수 인 OTOH는 동일한 오류가 발생하면 EM PTY와 같은 컴파일러 오류를 생성합니다.

자신의 상수를 정의하는 것이 여전히 좋습니다. 누군가 실수로 초기화를 변경할 수는 있지만 광범위하게 사용되기 때문에 이러한 오류의 영향은 단일 사용 사례의 오류보다 눈에 띄기 어렵습니다.

이것은 리터럴 값 대신 상수를 사용하면 얻을 수있는 일반적인 이점 중 하나입니다. 사람들은 일반적으로 수십 곳에서 사용되는 값에 상수를 사용하면 한 곳에서 해당 값을 쉽게 업데이트 할 수 있습니다. 덜 자주 인정되는 것은 이러한 변경이 모든 곳에 표시되기 때문에 실수로 값이 수정되는 것을 방지한다는 것입니다. 따라서 ""는 EMPTY보다 짧지 만 ""보다 EMPTY를 사용하는 것이 더 안전합니다.

따라서 원래의 질문으로 돌아가서, 우리는 언어 설계자들이 자주 사용되는 리터럴 값에 상수를 제공한다는 이점을 알지 못했을 것입니다. Java에서 문자열 상수가 추가 된 것을 보게 될 것입니다.


-16

주장 ""하고 String.Empty상호 교환이 가능하거나 ""더 나은 사람들에게는 매우 잘못되었습니다.

당신이 할 때마다 myVariable = ""; 오브젝트의 인스턴스를 작성 중입니다. Java의 String 오브젝트에 EMPTY 공용 상수가 있으면 오브젝트 ""의 인스턴스는 1 개만 있습니다.

예 :-

String.EMPTY = ""; //Simply demonstrating. I realize this is invalid syntax

myVar0 = String.EMPTY;
myVar1 = String.EMPTY;
myVar2 = String.EMPTY;
myVar3 = String.EMPTY;
myVar4 = String.EMPTY;
myVar5 = String.EMPTY;
myVar6 = String.EMPTY;
myVar7 = String.EMPTY;
myVar8 = String.EMPTY;
myVar9 = String.EMPTY;

10 (String.EMPTY를 포함하여 11 개) 1 개의 객체를 가리키는 포인터

또는 :-

myVar0 = "";
myVar1 = "";
myVar2 = "";
myVar3 = "";
myVar4 = "";
myVar5 = "";
myVar6 = "";
myVar7 = "";
myVar8 = "";
myVar9 = "";

10 개의 객체를 가리키는 10 개의 포인터

이는 비효율적이며 대규모 응용 프로그램 전체에서 중요 할 수 있습니다.

Java 컴파일러 또는 런타임은 ""의 모든 인스턴스를 자동으로 동일한 인스턴스를 가리 키도록 충분히 효율적일 수 있지만 해당 결정을 내리는 데 추가 처리가 필요하지 않을 수도 있습니다.


9
잘못된에 따라 stackoverflow.com/questions/1881922/... 은 ""문자열이 문자열 풀에서 다시 사용됩니다.
RealHowTo

1
나는 그것이 같은 객체를 재사용 할 수 있다고 말했고 그렇다면 문자열 풀에서 해당 객체를 찾아야하기 때문에 여전히 덜 효율적입니다. 그럼에도 불구하고, String.Empty가 우수한 이유는 여러 가지가 있습니다. myVar = ""; 내가 이미 언급 한 성능 개선뿐만 아니라 가독성. 다른 이유가 없다면 문자열 리터럴을 만드는 대신 상수를 사용하는 것이 좋습니다. 코드를 유지 관리하는 것이 더 쉽습니다.
Antony Booth

1
JLS가 컴파일 타임에 상수가 리터럴로 처리 될 것이라고 말했기 때문에 성능 인수가 유효하지 않습니다 ( docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10). 5 ). 가독성이 더 좋은 주장입니다.
RealHowTo

3
@AntonySmith-Java를 조금 더 공부해야하거나 아마도 오류를 알 것입니다. Java 문자열은 변경할 수 없으며 풀에 있습니다. 따라서 코드에서 여러 번 발견 되더라도 JVM에는 ""에 대해 하나의 String 객체 만 있습니다. 다음을 수행하여 문자열이 비어 있는지 확인할 수 있습니다.if (text == "")
Ajoy Bhatia

2
잘못된. 이 댓글은 삭제해야합니다.
Elad Tabak
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.