JavaRush /Java Blog /Random-KO /번역: Java에서 문자열 객체 생성 - " " 또는 생성자를 사용합니까?
FellowSparrow
레벨 12
Lvov

번역: Java에서 문자열 객체 생성 - " " 또는 생성자를 사용합니까?

Random-KO 그룹에 게시되었습니다
원본: " " 또는 생성자를 사용하여 Java 문자열을 생성하시겠습니까? X Wang 작성 번역: Java에서 문자열 객체 생성 - 사용법Java에서는 다음 두 가지 방법을 사용하여 문자열을 만들 수 있습니다.
String x = "abc";
String y = new String("abc");
큰따옴표를 사용하는 것과 생성자를 사용하는 것의 차이점은 무엇입니까?

1. 큰따옴표 대 건설자

이 질문은 두 가지 간단한 예를 보면 답할 수 있습니다. 예시 1:
String a = "abcd";
String b = "abcd";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True
a==ba둘 다 동일한 개체(메서드 영역에서 리터럴(아래 문자열 리터럴)로 선언된 문자열)를 참조하기 때문에 true입니다 b(독자에게 리소스의 소스를 참조하도록 합니다: Java 이해를 위한 상위 8개 다이어그램 , 다이어그램 8). 동일한 문자열 리터럴이 두 번 이상 생성되면 문자열의 복사본 하나만 메모리에 저장됩니다(이 경우에는 "abcd"). 이것을 "문자열 인턴"이라고 합니다. 컴파일 타임에 처리되는 모든 문자열 상수는 Java에서 자동으로 인턴됩니다. 예시 2:
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d);  // False
System.out.println(c.equals(d)); // True
c==d메모리(힙)에 있는 서로 다른 두 개체를 참조하기 c때문에 false입니다 . d서로 다른 객체는 항상 서로 다른 참조를 갖습니다. 이 다이어그램은 위에서 설명한 두 가지 상황을 보여줍니다. 번역: Java에서 문자열 객체 생성 - 사용법

2. 프로그램 실행 중 문자열 인터닝

저자는 LukasEder에게 감사를 표합니다(아래 주석은 그의 것임). 생성자를 사용하여 두 개의 문자열이 생성된 경우에도 프로그램 실행 중에 문자열 인터닝이 발생할 수도 있습니다.
String c = new String("abcd").intern();
String d = new String("abcd").intern();
System.out.println(c == d);  // Now true
System.out.println(c.equals(d)); // True

3. 큰따옴표를 사용해야 하는 경우와 생성자를 사용해야 하는 경우

리터럴 "abcd"는 항상 String 유형이기 때문에 생성자를 사용하면 불필요한 객체가 추가로 생성됩니다. 따라서 문자열을 생성해야 하는 경우에는 큰따옴표를 사용해야 합니다. 실제로 힙에 새 개체를 만들어야 하는 경우 생성자를 사용해야 합니다. 사용 사례는 여기에 표시됩니다 (원본) . (아래에 번역된 텍스트를 제공합니다. 하지만 이 링크에서 해설자의 코드를 숙지하시기를 적극 권장합니다.)

JDK 6 및 JDK 7의 substring() 메소드

JDK 6 및 JDK 7의 substring() 메소드 작성자: X Wang JDK 6 및 JDK 7의 메소드 substring(int beginIndex, int endIndex)는 다릅니다. 이러한 차이점을 알면 이 방법을 더 잘 사용하는 데 도움이 될 수 있습니다. 읽기 쉽게 하기 위해 아래에서는 substring()전체 구문을 의미합니다. substring(int beginIndex, int endIndex).

1. substring()은 무엇을 합니까?

이 메서드는 substring(int beginIndex, int endIndex)문자 번호로 시작 beginIndex하고 문자 번호로 끝나는 문자열을 반환합니다 endIndex-1.
String x = "abcdef";
x = x.substring(1,3);
System.out.println(x);
산출:
bc

2. substring()이 호출되면 무슨 일이 발생합니까?

x불변성으로 인해 의 결과를 x에 할당하면 x.substring(1,3)완전히 x새로운 행을 가리킨다는 것을 알 수 있습니다 (다이어그램 참조). 번역: Java에서 문자열 객체 생성 - 사용법그러나 이 다이어그램은 완전히 정확하지는 않습니다. 힙에서 실제로 무슨 일이 일어나고 있는지 보여주지는 않습니다. 호출될 때 실제로 일어나는 일은 substring()JDK 6과 JDK 7에서 다릅니다.

3. JDK 6의 부분 문자열()

문자열 유형은 배열 유형에서 지원됩니다 char. JDK 6에서는 클래스에 , , 3 String개의 필드가 포함되어 있습니다 . 실제 문자 배열, 배열의 첫 번째 문자 인덱스, 줄의 문자 수를 저장하는 데 사용됩니다. 메서드가 호출되면 새 행이 생성되지만 변수 값은 여전히 ​​힙의 동일한 배열을 가리킵니다. 두 문자열의 차이점은 문자 수와 배열에 있는 시작 문자의 인덱스 값입니다. 아래 코드는 단순화되었으며 문제를 보여주기 위한 기본 사항만 포함되어 있습니다. char value[]int offsetint countsubstring()번역: Java에서 문자열 객체 생성 - 사용법
//JDK 6
String(int offset, int count, char value[]) {
	this.value = value;
	this.offset = offset;
	this.count = count;
}

public String substring(int beginIndex, int endIndex) {
	//check boundary
	return  new String(offset + beginIndex, endIndex - beginIndex, value);
}

4. JDK 6의 substring()으로 인해 발생하는 문제

매우 긴 문자열이 있지만 substring(). 작은 부분만 필요하지만 여전히 전체 문자열을 저장해야 하기 때문에 실행 문제가 발생합니다. JDK 6의 경우 문자열을 실제 하위 문자열로 변환하는 아래 코드가 솔루션입니다.
x = x.substring(x, y) + ""
STepeR 사용자가 질문을 작성했는데(그의 의견 참조), 포인트 4를 추가해야 할 것 같았습니다. " substring()JDK 6에서 발생한 문제"는 보다 광범위한 예입니다. 이것이 답변이 되기를 바라며 다른 사람들이 문제가 무엇인지 빨리 파악하는 데 도움이 되기를 바랍니다. 코드는 다음과 같습니다.
String a = "aLongLongString";
String b = a.substring(1, 2);
String c = a.substring(2, 6);
따라서 JDK 7에서 ba с유형의 객체에 대한 String메서드를 호출하여 생성된 substring()a 유형 의 객체 String는 힙에서 새로 생성된 두 개의 배열( Lfor b, ongLfor ) 을 참조합니다 c. 이 두 개의 새로운 배열은 a에서 참조하는 원래 배열과 함께 힙에 저장됩니다 aLongLongString. 저것들. 원래 배열은 어디에서도 사라지지 않습니다. 이제 JDK 6으로 돌아가 보겠습니다. JDK 6에서 힙에는 단일 배열이 포함됩니다 aLongLongString. 코드 라인을 실행한 후
String b = a.substring(1, 2);
String c = a.substring(2, 6);
객체는 객체에 해당하는 힙의 동일한 배열을 참조합니다 b. - 첫 번째 인덱스에서 두 번째까지의 요소, - 두 번째 인덱스에서 여섯 번째까지의 요소(번호는 0부터 시작함, 알림). 저것들. 분명히 JDK 6의 변수 또는 c에 대한 추가 액세스는 실제로 원래 배열의 원하는 요소가 힙에 "계산"되는 결과를 낳습니다. JDK 7에서는 변수 또는 c에 대한 추가 액세스로 인해 이미 생성되어 힙에 "활성"되어 있는 필요한 더 작은 배열에 액세스하게 됩니다. 저것들. 분명히 JDK 7은 이와 같은 상황에서 물리적으로 더 많은 메모리를 사용합니다. 그러나 가능한 옵션을 상상해 봅시다. 변수의 특정 하위 문자열이 변수에 할당되고 앞으로는 모든 사람이 개체 및 . 더 이상 누구도 단순히 변수 a에 액세스하지 않으며 이에 대한 참조도 없습니다(이것이 기사 작성자의 의미입니다). 결과적으로 어느 시점에서 가비지 수집기가 트리거되고 (물론 가장 일반적인 형태로) 2가지 다른 상황이 발생합니다. JDK 6 : 객체가 파괴됨(가비지 수집) , 그러나 - 원래의 거대한 배열 힙에는 살아 있습니다. 지속적 으로 사용되며 . JDK 7: 객체 a가 힙의 원래 배열과 함께 삭제됩니다. 이것이 JDK 6에서 메모리 누수를 일으킬 수 있는 지점입니다. cabcbbbcabcabc

5. JDK 7의 부분 문자열()

JDK 7에서는 이 방법이 개선되었습니다. JDK 7에서는 substring()실제로 힙에 새 배열을 생성합니다. 번역: Java에서 문자열 객체 생성 - 사용법
//JDK 7
public String(char value[], int offset, int count) {
	//check boundary
	this.value = Arrays.copyOfRange(value, offset, offset + count);
}

public String substring(int beginIndex, int endIndex) {
	//check boundary
	int subLen = endIndex - beginIndex;
	return new String(value, beginIndex, subLen);
}
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION