이 시리즈의 질문에 대해서는 Java를 공부하는 모든 사람이 이해해야 합니다. 물론 그냥 재미로 자바를 배우신다면 상관없습니다. 초급 수준을 넘어섰다고 생각하지만 이러한 문제를 잘 이해하지 못하는 경우 초급 팀에 자신을 추가하세요.
질문 1: 내가 무엇을 말하고 있습니까?
String s = "안녕하세요!";
많은 사람들이 이 작업을 수행했지만 정확히 무엇을 선언합니까? 대답은 일반적으로 "Hello world!"라는 내용이 포함된 문자열입니다. 그러한 모호한 대답은 종종 불분명한 개념의 원천이 됩니다. 만약 정확한 답변을 드린다면 아마도 절반의 사람들이 틀리게 답변할 것입니다.
이 명령문은 String 유형의 모든 객체를 가리킬 수 있는 "s"라는 객체에 대한 참조를 선언합니다. 현재는 String 유형 객체 "Hello world!"를 가리킵니다. 이것이 실제로 일어난 일입니다. 우리는 String 객체를 선언하지 않았고 단지 String 객체만을 가리킬 수 있는 참조 변수를 선언했습니다. 따라서 방금 명령문 다음에 다른 문장을 실행하면 다음과 같습니다.
문자열 문자열 = s;
string이라는 이름의 String 개체만 가리킬 수 있는 또 다른 참조를 선언했습니다. 두 번째 개체는 생성되지 않습니다. String은 여전히 원래 개체를 가리킵니다. 즉, s와 동일한 개체를 가리킵니다.
질문 2: "=="와 같음 메서드의 차이점은 무엇인가요?
== 연산자는 특히 변수 값이 같은지 비교하는 데 사용됩니다. 이해하기 쉬운 것은 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
정수 a=10;
정수 b=10;
그러면 a==b는 참이 됩니다.
하지만 이해하기 어려운 점은 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
String a=new String("foo");
String b=new String("foo");
그러면 a==b는 false를 반환합니다.
이전 게시물에 따르면 객체 변수는 실제로 참조이며 해당 값은 객체 자체가 아닌 객체가 위치한 메모리 주소를 가리킵니다. a와 b 모두 new 연산자를 사용합니다. 이는 "foo"라는 내용이 포함된 두 개의 문자열이 메모리에 생성된다는 의미입니다. "two"가 있으므로 자연스럽게 서로 다른 메모리 주소에 위치하게 됩니다. a와 b의 값은 실제로는 서로 다른 두 메모리 주소의 값이므로 "==" 연산자를 사용하면 결과가 false가 됩니다. a와 b가 가리키는 객체는 "foo"라는 내용을 가지며 "동일"해야 한다는 것은 사실이지만 == 연산자는 객체 내용의 비교를 포함하지 않습니다.
객체 내용의 비교는 바로 equals 메소드가 하는 일이다.
Object 객체의 equals 메소드가 어떻게 구현되는지 살펴보세요:
다음과 같이 코드 코드를 복사합니다.
부울 같음(객체 o){
이것을 반환==o;
}
객체 객체는 기본적으로 == 연산자를 사용합니다. 따라서 자체 생성된 클래스가 equals 메서드를 재정의하지 않으면 클래스는 ==를 사용하고 equals를 사용하여 동일한 결과를 얻습니다. 또한 Object의 equals 메소드는 equals 메소드가 달성해야 하는 목표, 즉 두 객체의 내용이 동일한지 비교하는 목표를 달성하지 못한다는 것을 알 수 있습니다. 대답은 클래스 작성자가 결정해야 하므로 Object는 이 작업을 클래스 작성자에게 맡깁니다.
극단적인 클래스를 살펴보십시오.
다음과 같이 코드 코드를 복사합니다.
클래스 몬스터{
비공개 문자열 콘텐츠;
...
부울 같음(다른 객체){ return true;}
}
나는 같음 메서드를 재정의했습니다. 이 구현을 통해 Monster 인스턴스 간의 비교는 내용에 관계없이 항상 true를 반환합니다.
따라서 객체의 내용이 동일한지 확인하기 위해 equals 메소드를 사용할 때 이를 당연하게 여기지 마십시오. 왜냐하면 당신은 그것들이 동일하다고 생각할 수도 있지만 이 클래스의 작성자는 그렇게 생각하지 않으며 클래스의 equals 메소드 구현은 그에 의해 제어되기 때문입니다. 같음 메서드를 사용해야 하거나 해시 코드 기반 컬렉션(HashSet, HashMap, HashTable)을 사용해야 하는 경우 Java 문서를 확인하여 이 클래스의 같음 논리가 구현되는 방법을 확인하세요.
질문 3: 문자열이 변경되었나요?
아니요. String은 불변 클래스로 설계되었기 때문에 해당 객체는 모두 불변 객체입니다. 다음 코드를 살펴보십시오.
다음과 같이 코드 코드를 복사합니다.
문자열 s = "안녕하세요";
s = s + "세계!";
s가 가리키는 대상이 바뀌었나요? 이 결론은 이 시리즈의 첫 번째 기사의 결론에서 쉽게 도출될 수 있습니다. 무슨 일이 일어났는지 봅시다. 이 코드에서 s는 원래 내용이 "Hello"인 String 개체를 가리킨 다음 s에 대해 + 연산을 수행했습니다. s가 가리키는 개체가 변경되었습니까? 대답은 '아니요'입니다. 이때 s는 더 이상 원본 개체를 가리키지 않고 "Hello world!"라는 내용을 가진 다른 String 개체를 가리키지만, 원본 개체는 여전히 메모리에 존재하지만 참조 변수 s는 더 이상 이를 가리키지 않습니다.
위의 설명을 통해 우리는 쉽게 또 다른 결론을 도출할 수 있습니다. 문자열이 자주 다양한 방식으로 수정되거나 예측할 수 없게 수정되는 경우 String을 사용하여 문자열을 표현하면 많은 메모리 오버헤드가 발생하게 됩니다. String 개체는 생성된 후에는 변경할 수 없으므로 각각의 다른 문자열을 나타내려면 String 개체가 필요합니다. 이때는 각각의 문자열에 대해 새 개체를 생성하는 대신 수정이 가능한 StringBuffer 클래스를 사용하는 것이 좋습니다. 게다가 이 두 유형 간의 정책 변경은 매우 간단합니다.
동시에, 동일한 내용의 문자열을 사용하려는 경우 매번 새 문자열을 만들 필요가 없다는 것도 알 수 있습니다. 예를 들어 생성자에서 s라는 문자열 참조 변수를 초기화하고 이를 초기 값으로 설정하려면 다음을 수행해야 합니다.
다음과 같이 코드 코드를 복사합니다.
공개 수업 데모 {
개인 문자열 s;
…
공개 데모 {
s = "초기값";
}
…
}
s = new String("초기 값"); 대신
후자는 성능이 낮고 메모리 소비가 크며 의미가 없는 새 개체를 생성하기 위해 매번 생성자를 호출합니다. String 개체는 변경할 수 없으므로 하나의 String 개체만 사용하여 동일한 내용을 가진 문자열을 나타낼 수 있습니다. . 즉, 위의 생성자를 여러 번 호출하여 여러 대상을 생성하는 경우 문자열 유형 속성은 모두 동일한 대상을 가리킵니다.
위의 결론은 또한 문자열 상수의 경우 내용이 동일하면 광주 자바 트레이닝(Guangzhou Java Training)이 동일한 문자열 객체를 나타낸다고 믿는다는 사실에 근거합니다. new 키워드를 사용하여 생성자를 호출하면 내용이 동일한지 여부에 관계없이 항상 새 대상이 생성됩니다.
String 클래스를 불변 클래스로 기술해야 하는 이유는 그 목적에 따라 결정됩니다. 실제로 String뿐만 아니라 Java 표준 클래스 라이브러리의 많은 클래스도 불변입니다. 시스템을 개발할 때 관련된 값 집합을 전달하기 위해 불변 클래스를 설명해야 하는 경우가 있는데, 이는 목표 지향적 사고의 표현이기도 합니다. 예를 들어 불변 클래스는 읽기 전용이므로 여러 스레드의 동시 액세스에 문제가 없습니다. 물론 몇 가지 단점도 있습니다. 예를 들어 각각의 상황마다 이를 표현하기 위한 객체가 필요하므로 기능적인 문제가 발생할 수 있습니다. 따라서 Java 표준 클래스 라이브러리는 StringBuffer라는 변수 버전도 제공합니다.