>Java >java지도 시간 >String은 equals 메소드와 ==를 사용하여 무엇을 비교합니까?

String은 equals 메소드와 ==를 사용하여 무엇을 비교합니까?

高洛峰
高洛峰원래의
2016-12-16 09:38:271334검색

equals 메소드와 ==

우선 String은 객체로도 사용할 수 있고, 기본 타입으로도 사용할 수 있다는 것은 다들 아시죠. 여기서 의미하는 바는 이를 기본 유형으로 사용한다는 것은 String s = "Hello"와 같은 사용 방법만 참조한다는 것입니다. int i = 1;과 같이 기본 유형 int와 동일한 방식으로 사용됩니다. 객체로 사용한다는 것은 String s = new String("Hello")와 같이 new 키워드를 통해 새 객체를 생성하는 것을 의미합니다. 그러나 내부 동작은 실제로 객체를 생성하는데, 이에 대해서는 나중에 설명하겠습니다.

둘째, String 객체의 비교 방법을 이해해야 합니다. Java의 객체 간 비교에는 두 가지 개념이 있습니다. 하나는 "=="를 사용하여 두 개의 String 유형 변수를 참조하는 것입니다. 변수가 동일한 String 개체를 참조하는 경우(즉, 동일한 메모리 힙을 가리키는 경우) "==" 비교 결과는 true입니다. 다른 하나는 비교를 위해 Object 객체의 equals() 메서드를 사용하는 것입니다. String 객체는 Object에서 상속되며 equals() 메서드가 재정의됩니다. 두 String 객체를 equals() 메서드를 통해 비교할 때 String 객체에 캡슐화된 문자열 내용이 실제로 비교됩니다. 즉, 두 String 객체에 캡슐화된 문자열 내용이 동일한 경우(동일한 대소문자 포함) 그런 다음 equals() 메서드는 true를 반환합니다.

이제 String 객체 생성에 대한 자세한 분석을 시작하겠습니다.

1. /////////////////// /// ////////////////////////////////////////////// ///////

String s1 = new String("Hello");

String s2 = new String("Hello");

System.out .println(s1 == s2 );

System.out.println(s1.equals(s2));

위 코드 세그먼트의 인쇄 결과는 다음과 같습니다.

false

true

이 결과는 누구나 쉽게 이해할 수 있다고 생각합니다. 두 개의 String 유형 변수 s1과 s2는 각각 new 키워드를 통해 새로운 String 객체를 생성합니다. 생성된 각 객체에 대한 새로운 블록, 독립 메모리 힙. 따라서 "=="를 통해 동일한 객체를 참조하는지 비교하면 false가 반환됩니다. equals() 메서드를 통해 비교하면 두 객체에 캡슐화된 문자열 내용이 정확히 동일하므로 true가 반환됩니다.

2. ///////////////////////////////////// / /////////////////////////////////////

문자열 s1 = new String("안녕하세요");

String s2 = s1;

System.out.println(s1 == s2);

System.out.println(s1 .equals(s2));

위 코드 조각의 인쇄 결과는 다음과 같습니다.

true

true

이 결과는 더 잘 이해되어야 합니다. 변수 s1은 여전히 ​​new 키워드를 통해 새로운 String 객체가 생성되는데 여기서 s2는 new 키워드를 통해 새로운 String 객체를 생성하지 않고 s1을 s2에 직접 할당, 즉 s1의 참조를 s2에 할당하는 것입니다. s2가 참조하는 객체는 실제로 s1이 참조하는 객체입니다. 따라서 "=="와 비교하면 true가 반환됩니다. 모두 동일한 객체를 참조하므로 equals() 메서드를 통해 비교하면 반드시 true를 반환합니다. 여기서 equals() 메서드는 실제로 동일한 객체를 비교하는 것이므로 자신과 동일해야 합니다.

3. ///////////////////////////////////// / ///////////////////////////////////

문자열 s1 = "안녕하세요" ;

문자열 s2 = "안녕하세요";

System.out.println(s1 == s2);

System.out.println(s1.equals(s2) );

위 코드 조각의 인쇄 결과는 다음과 같습니다.

true

true

왜 이런 결과가 나온 걸까요? 그럼 분석해 보겠습니다. 우선, 이 두 String 개체는 new 키워드를 통해 생성되지 않고 기본 유형으로 사용됩니다. 따라서 가상 머신은 이 두 String 개체에 대해 새 메모리 힙을 할당하지 않고 String 버퍼 풀에 할당합니다. 찾다.

먼저 s1에 대해 String 버퍼 풀에 "Hello"와 동일한 값을 갖는 String 객체가 있는지 찾아보세요. 이때 String 버퍼 풀은 비어 있고 동일한 값을 갖는 String 객체가 없습니다. 값이므로 가상 머신은 String 버퍼 풀에 있습니다. 이 String 객체를 생성하려면 작업은 new String("Hello");입니다. 그런 다음 이 String 객체의 참조를 s1에 할당합니다.

그런 다음 s2를 검색하여 String 버퍼 풀에 "Hello"와 동일한 값을 가진 String 객체가 있는지 확인합니다. 이때 가상 머신은 동일한 값을 가진 String 객체를 찾았습니다. 객체는 실제로 s1 객체에 대해 생성되었습니다. 이제 동일한 값을 가진 개체가 발견되었으므로 가상 머신은 더 이상 이에 대한 새 String 개체를 생성하지 않고 기존 String 개체의 참조를 s2에 직접 할당합니다.

s1과 s2는 동일한 String 객체를 참조하므로, 즉 서로 동일하므로 위의 두 가지 비교 방법은 true를 반환합니다.

이제 String 객체의 기본 개념을 이해하셨을 것입니다. 이제 요약하겠습니다:

문자열을 기본 유형으로 사용:

1. String이 기본 유형으로 사용되면 이 String 객체를 String 버퍼 풀이 소유한 것으로 간주합니다.

2. String을 기본 유형으로 사용하고 현재 String 버퍼 풀에 지정된 값과 동일한 String 개체가 없으면 가상 머신은 이에 대한 새 String 개체를 생성하여 String 버퍼 풀에 저장합니다.

3. String을 기본 타입으로 사용하고, 이때 String 버퍼 풀에 지정된 값과 동일한 String 객체가 있는 경우, 가상 머신은 이에 대한 새로운 String 객체를 생성하지 않고 기존 String 객체에 대한 참조를 직접 반환합니다. 문자열 객체.

문자열을 객체로 사용:

1. String이 개체로 사용되는 경우 가상 머신은 이 개체에 대해 새 String 개체를 생성합니다. 즉, 이 개체에 대해 새 메모리 힙을 할당하며 이 개체는 String 버퍼 풀에 의해 소유되지 않습니다. 즉, 독립적입니다. .

위 내용을 이해하신 후 다음 코드를 살펴보시기 바랍니다.

4. ///////////////////// / //////////////////////////////////////////////// ///// ///

String s1 = "안녕하세요";

String s2 = new String("안녕하세요");

System.out.println( s1 == s2) ;

System.out.println(s1.equals(s2));

위 코드 세그먼트의 인쇄 결과는 다음과 같습니다.

false

맞다

위의 요약을 토대로 분석을 진행해 보세요. 첫 번째 줄에서는 String을 기본 유형으로 사용하므로 s1에서 참조하는 객체는 String 버퍼 풀에 속합니다. 그리고 이때 String 버퍼 풀에는 동일한 값을 갖는 String 개체가 없으므로 가상 머신은 이를 위해 새로운 String 개체, 즉 new String("Hello");을 생성합니다. 두 번째 줄은 String을 객체로 사용하므로 s2가 참조하는 객체는 String 버퍼 풀에 속하지 않습니다. 즉, 독립적입니다. new 키워드를 통해 가상 머신은 이 목적을 위해 새 String 객체를 생성합니다. 즉, 이에 대해 새 메모리 힙을 할당합니다. 따라서 "==" 비교 결과는 거짓입니다. s1과 s2는 동일한 객체를 참조하지 않고 독립적으로 존재하기 때문입니다. 두 객체에 의해 캡슐화된 문자열 내용이 정확히 동일하기 때문에 equals() 메서드는 true를 반환합니다.

이제 모든 분들이 String 객체가 무엇인지 완전히 이해하셨을 거라 믿습니다. :) 그러나 여기에서 끝나지 않습니다. 왜냐하면 String 객체에는 더 깊은 적용이 있기 때문입니다.

여기서는 String 개체의 intern() 메서드 적용을 분석합니다.

intern() 메서드는 문자열 개체의 정식 표현, 즉 다음과 같은 문자열을 반환합니다. 동일한 콘텐츠 문자열이지만 고유한 문자열의 문자열 버퍼 풀에서 가져온 것입니다. 좀 장황하게 들리지만 그 메커니즘은 실제로 다음과 같습니다:

String s = new String("Hello");

s = s.intern();

위 코드 세그먼트의 기능적 구현은 다음 코드 세그먼트로 간단히 볼 수 있습니다.

String s = "Hello";

또 궁금하시죠? 그런 다음 두 번째 코드 조각을 먼저 살펴보세요. 두 번째 코드 조각의 의미는 문자열 버퍼 풀에서 동일한 값을 가진 문자열 개체에 대한 참조를 가져와 s에 할당하는 것입니다. String 버퍼 풀에 동일한 값을 가진 String 개체가 없으면 새 String 개체가 생성됩니다. 그렇다면 첫 번째 코드는 무엇을 의미할까요? new 키워드를 통해 생성된 개체에 대해 가상 머신은 이에 대해 새 메모리 힙을 할당한다는 것을 알고 있습니다. 사소하게 동일한 콘텐츠를 가진 개체를 생성하는 경우, 가상 머신은 해당 콘텐츠가 정확히 동일하더라도 이에 대해 많은 새로운 메모리 힙을 할당합니다. String 개체를 예로 들면, 동일한 내용(new String("Hello"))을 가진 10개의 String 개체가 연속적으로 생성되면 가상 머신은 이에 대해 10개의 독립적인 메모리 힙을 할당합니다. 생성된 String 객체의 문자열 내용이 매우 크다고 가정합니다. Stirng 객체가 1M 크기의 문자열 내용을 캡슐화한다고 가정하면, 10개의 동일한 String 객체를 생성하면 의미 없는 방식으로 9M의 메모리 공간이 낭비됩니다. 우리는 String이 최종 클래스이고 그것이 캡슐화하는 것은 문자열 상수라는 것을 알고 있습니다. 따라서 String 개체의 내부(문자열) 값은 생성된 후에 변경할 수 없으므로 String 개체를 공유할 수 있습니다. 따라서 방금 언급한 가정에 대해 동일한 내용으로 생성한 10개의 String 객체에 대해 실제로는 이를 위해 하나의 String 객체만 생성하면 되며 이 객체는 다른 String 변수와 공유됩니다. 이 메커니즘을 구현하기 위한 유일하고 간단한 방법은 문자열 버퍼 풀을 사용하는 것입니다. 왜냐하면 문자열 버퍼 풀에는 동일한 내용을 가진 문자열 개체가 없기 때문입니다. intern() 메소드는 이 메커니즘을 사용하는 방법입니다. 인스턴스화된 String 객체에 대해 intern() 메서드를 호출한 후 가상 머신은 String 버퍼 풀에서 이 Stirng 객체에 의해 캡슐화된 문자열 내용과 동일한 값을 가진 String 객체를 검색한 다음 참조를 원래 String 객체에 할당합니다. . 문자열 유형 변수. 문자열 버퍼 풀에서 이 문자열 개체에 의해 캡슐화된 문자열 내용과 동일한 값을 가진 문자열 개체가 없는 경우 가상 머신은 이 목적을 위해 새 문자열 개체를 생성하고 해당 참조를 참조하는 문자열 유형 변수에 할당합니다. 원본 문자열 객체. 이렇게 하면 동일한 String 개체를 공유한다는 목적이 달성되고 new 키워드를 통해 생성된 원래 String 개체는 가비지 수집기에 의해 폐기되고 재활용됩니다. 이렇게 하면 메모리 사용량이 줄어들고 성능이 향상될 뿐만 아니라 동일한 String 객체가 공유되므로 String 객체 비교가 더욱 편리해집니다. 따라서 두 String 객체가 동일한지 확인하려면 " ==를 사용하여 비교하기만 하면 됩니다. , 비교를 위해 equals() 메소드를 사용하는 대신 String 객체의 equals() 메소드가 문자열 내용을 분해한 다음 하나씩 비교하기 때문에 사용이 더 편리할 뿐만 아니라 성능도 향상됩니다. , 문자열 내용이 매우 큰 경우 이 비교 작업으로 인해 성능이 크게 저하됩니다.

이렇게 말했지만 아직 특정 애플리케이션에 대해 다소 모호할 수 있으므로 위의 개념을 설명하기 위해 간단한 예를 들어 보겠습니다.

메시지가 있는 클래스가 있다고 가정합니다. 로깅 기능 방식으로, 사용자가 보낸 메시지를 기록하고(메시지 내용이 크고, 반복률이 높다고 가정), 메시지를 수신한 순서대로 목록에 기록하는 방식이다. 몇몇 친구들은 다음과 같이 디자인할 것 같아요:

import java.util.*;

public class Messages {

ArrayList message = new ArrayList();

public void Record(String msg) {

messages.add(msg);

}

public List getMessages() {

return 메시지

}

}

이 디자인 좋은가요? 동일한 메시지를 Record() 메서드에 반복적으로 보내고(메시지는 서로 다른 사용자로부터 왔기 때문에 각 메시지는 새로운 String("...")로 간주될 수 있음) 메시지 내용이 크다고 가정해 보겠습니다. will 메시지 목록의 모든 레코드는 내용은 동일하지만 새로 생성된 독립적인 String 객체이기 때문에 메모리 공간을 크게 낭비합니다. 그렇다면 어떻게 최적화할 수 있을까요? 다음 최적화된 예를 참조하세요.

import java.util.*;

public class Messages {

ArrayList messages = new ArrayList();

공개 무효 레코드(String msg) {

messages.add(msg.intern());

}

public List getMessages() {

return message;

}

}

보시다시피 원래 Record() 메서드는 message.add (msg);의 코드 세그먼트는 msg 매개변수에 대해 intern() 메소드만 호출하는 message.add(msg.intern());이 되었습니다. 이는 중복 메시지에 대한 공유 메커니즘을 생성하여 메모리 비용을 줄입니다. 소비, 성능 향상.

이 예는 사실 다소 무리가 있지만 위의 개념을 설명하기 위한 것입니다!

이 시점에서 이러한 개념을 염두에 두기만 하면 향후의 모든 복잡한 문자열 애플리케이션을 이를 기반으로 분석할 수 있습니다.




String이 각각 비교하기 위해 equals 메서드와 ==를 사용하는 것에 대한 자세한 관련 기사를 확인하세요. PHP 중국어 웹사이트를 팔로우하세요!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.