JavaRush /Java Blog /Random-KO /Java 및 문자열 비교의 같음 - 문자열 비교

Java 및 문자열 비교의 같음 - 문자열 비교

Random-KO 그룹에 게시되었습니다
안녕하세요! 오늘 우리는 매우 중요하고 흥미로운 주제, 즉 Java에서 객체를 서로 비교하는 equals() 에 대해 이야기하겠습니다. 그리고 실제로 Java에서 어떤 경우에 Object A가 Object B 와 같을 까요 ? 같음 및 문자열 비교 - 1예를 작성해 봅시다:
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
콘솔 출력:

false
알았어, 그만해. 실제로 이 두 대의 자동차가 동일하지 않은 이유는 무엇입니까? 우리는 그들에게 동일한 속성을 부여했지만 비교 결과는 거짓입니다. 대답은 간단합니다. 연산자는 ==객체의 속성이 아니라 링크를 비교합니다. 두 개체에 500개의 동일한 속성이 있더라도 비교 결과는 여전히 거짓입니다. 결국 링크는 두 개의 서로 다른 개체car1 , 즉 두 개의 서로 다른 주소를 가리킵니다 . 사람들을 비교하는 상황을 상상해보십시오. 아마 세상에는 당신과 같은 이름, 눈 색깔, 나이, 키, 머리 색깔 등을 가진 사람이 있을 것입니다. 즉, 당신은 여러 면에서 비슷하지만 여전히 쌍둥이가 아니며, 특히 같은 사람이 아닙니다. 연산자는 두 객체를 비교할 때 거의 동일한 논리를 적용합니다. 하지만 프로그램에 다른 논리가 필요하면 어떻게 될까요? 예를 들어 프로그램이 DNA 분석을 시뮬레이션하는 경우입니다. 그녀는 두 사람의 DNA 코드를 비교하여 그들이 쌍둥이인지 확인해야 합니다. car2 같음 및 문자열 비교 - 2==
public class Man {

   int dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1 == man2);
   }
}
콘솔 출력:

false
결과가 같다는 것은 논리적이지만(결국 우리는 아무것도 바꾸지 않았습니다), 지금은 만족스럽지 않습니다! 실제로, 실생활에서 DNA 분석은 우리가 쌍둥이를 마주하고 있음을 100% 보장합니다. 그러나 우리 프로그램과 운영자는 ==우리에게 다르게 말합니다. 이 동작을 어떻게 변경하고 DNA 테스트가 일치하면 프로그램이 올바른 결과를 생성하는지 확인할 수 있습니까? 이를 위해 Java에서는 equals() 라는 특수 메소드가 생성되었습니다 .

Java의 Equals() 메소드

toString()앞서 논의한 메소드와 마찬가지로 , equals()는Object 다른 모든 클래스가 파생되는 Java에서 가장 중요한 클래스인 클래스에 속합니다 . 그러나 equals() 자체는 어떤 방식으로든 프로그램의 동작을 변경하지 않습니다.
public class Man {

   String dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = "111122223333";

       Man man2 = new Man();
       man2.dnaCode = "111122223333";

       System.out.println(man1.equals(man2));
   }
}
콘솔 출력:

false
똑같은 결과가 나오는데 왜 이 방법이 필요한 걸까요? :/ 간단 해. 사실 이제 우리는 이 메서드를 클래스 자체에 구현된 대로 사용했습니다 Object. 그리고 클래스 코드로 가서 Object이 메서드가 어떻게 구현되고 무엇을 하는지 살펴보면 다음과 같은 내용을 볼 수 있습니다.
public boolean equals(Object obj) {
   return (this == obj);
}
이것이 우리 프로그램의 동작이 변하지 않은 이유입니다! 클래스의 equals() 메소드 내부에는 Object동일한 참조 비교인 가 있습니다 ==. 하지만 이 방법의 비결은 이를 재정의할 수 있다는 것입니다. 재정의란 클래스에 자신만의 equals() 메서드를 작성하고 Man원하는 방식으로 작동하도록 만드는 것을 의미합니다! 이제 우리는 수표가 man1.equals(man2)본질적으로 man1 == man2. 이 상황에서 우리가 할 일은 다음과 같습니다.
public class Man {

   int dnaCode;

   public boolean equals(Man man) {
       return this.dnaCode ==  man.dnaCode;
   }

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1.equals(man2));

   }
}
콘솔 출력:

true
전혀 다른 결과! 표준 메소드 대신 자체적인 equals() 메소드를 작성함으로써 올바른 동작을 달성했습니다. 이제 두 사람이 동일한 DNA 코드를 가지고 있으면 프로그램은 "DNA 분석 결과 쌍둥이인 것으로 나타났습니다"라고 말하고 true를 반환합니다! 클래스에서 equals() 메서드를 재정의하면 필요한 개체 비교 논리를 쉽게 만들 수 있습니다. 우리는 일반적인 용어로만 객체 비교를 다루었습니다. 우리는 앞으로 이 주제에 관해 별도의 대규모 강의를 가질 것입니다 (관심이 있으시면 지금 바로 읽으실 수 있습니다).

Java의 문자열 비교 - 문자열 비교

문자열 비교를 다른 모든 것과 별도로 처리하는 이유는 무엇입니까? 사실, 프로그래밍의 라인은 완전히 다른 이야기입니다. 첫째, 인류가 작성한 모든 자바 프로그램을 살펴보면 그 안에 있는 객체의 약 25%가 자바로 구성되어 있습니다. 그러므로 이 주제는 매우 중요합니다. 둘째, 문자열을 비교하는 과정은 실제로 다른 객체와 상당히 다릅니다. 간단한 예를 살펴보겠습니다.
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
콘솔 출력:

false
그런데 왜 거짓인가? 줄은 단어 하나하나가 정확히 동일합니다. // 다음과 같이 가정할 수 있습니다. 이는 연산자가 == 참조를 비교하기 때문입니다! 결국, s1그들은 s2메모리에 다른 주소를 가지고 있습니다. 이런 생각이 들었다면 예제를 다시 실행해 보겠습니다.
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       System.out.println(s1 == s2);
   }
}
이제 두 개의 링크도 있지만 결과는 반대 방향으로 변경되었습니다. 콘솔 출력:

true
완전히 혼란스러워요? :) 알아 봅시다. 연산자는 ==실제로 메모리의 주소를 비교합니다. 이 규칙은 항상 유효하므로 의심할 필요가 없습니다. 이는 s1 == s2true를 반환하면 이 두 문자열이 메모리에서 동일한 주소를 갖는다는 것을 의미합니다. 그리고 실제로 그렇습니다! String pool이제 문자열을 저장하기 위한 특별한 메모리 영역인 문자열 풀( ) 에 대해 알아볼 시간입니다. 같음 및 문자열 비교 - 3문자열 풀은 프로그램에서 생성하는 모든 문자열 값을 저장하는 영역입니다. 무엇을 위해 만들어졌나요? 앞서 언급했듯이 문자열은 모든 객체에서 큰 부분을 차지합니다. 큰 프로그램에서는 많은 줄이 생성됩니다. 메모리를 절약하려면 이것이 필요합니다. String Pool필요한 텍스트가 있는 줄이 거기에 배치되고 앞으로 새로 생성된 링크는 동일한 메모리 영역을 참조하므로 매번 추가 메모리를 할당할 필요가 없습니다. 를 작성할 때마다 String = “........”프로그램은 문자열 풀에 해당 텍스트가 포함된 행이 있는지 확인합니다. 있는 경우 새 항목이 생성되지 않습니다. 그리고 새 링크는 이 문자열이 저장된 문자열 풀의 동일한 주소를 가리킵니다. 그러므로 우리가 프로그램에 글을 썼을 때
String s1 = "JavaRush is the best site to learn Java!";
String s2 = "JavaRush is the best site to learn Java!";
링크는 와 s2정확히 같은 위치를 가리킵니다 s1. 첫 번째 명령은 필요한 텍스트로 문자열 풀에 새 줄을 만들었고, 두 번째 명령에서는 단순히 s1. 동일한 텍스트로 최소 500줄을 더 만들 수 있으며 결과는 변경되지 않습니다. 멈추다. 그런데 이 예가 이전에는 왜 효과가 없었을까요?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
내 생각에, 당신은 이미 그 이유가 무엇인지 짐작하고 있을 것입니다. :) 더 읽기 전에 추측해 보세요. 이 두 줄이 다르게 생성된 것을 볼 수 있습니다. 하나는 운영자의 도움을 받는 것이고 new, 두 번째는 그렇지 않은 것입니다. 이것이 바로 이유입니다. new 연산자는 객체를 생성할 때 해당 객체에 대한 메모리에 새로운 영역을 강제로 할당합니다 . 그리고 로 생성된 줄은 new다음으로 끝나지 않습니다 String Pool. 텍스트가 'a.'의 동일한 줄과 정확히 동일하더라도 별도의 개체가 됩니다 String Pool. 즉, 다음 코드를 작성하면:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       String s3 = new String("JavaRush is the best site to learn Java!");
   }
}
메모리에서는 다음과 같이 보입니다. 같음 및 문자열 비교 - 4새 객체가 생성될 때마다 new새 줄 안의 텍스트가 동일하더라도 메모리에 새 영역이 할당됩니다! 우리는 연산자를 정리한 것 같지만 ==, 새로운 친구인 equals() 메소드는 어떻습니까?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1.equals(s2));
   }
}
콘솔 출력:

true
흥미로운. 우리는 정확히 무엇을 알고 s1있으며 s2기억의 다른 영역을 가리킵니다. 그러나 그럼에도 불구하고, equals() 메소드는 그것들이 동일하다고 말합니다. 왜? 위에서 우리가 필요한 방식으로 객체를 비교하도록 클래스에서 equals() 메서드를 재정의할 수 있다고 말한 것을 기억하십니까? 그것이 그들이 수업시간에 했던 일입니다 String. 여기에는 재정의된 equals() 메서드가 있습니다. 그리고 링크가 아닌 문자열의 문자 순서를 비교합니다. 문자열의 텍스트가 동일한 경우 문자열 풀이나 별도의 메모리 영역 등 문자열이 생성된 방법과 저장 위치는 중요하지 않습니다. 비교 결과는 참이 됩니다. 그런데 Java를 사용하면 대소문자를 구분하지 않고 문자열을 정확하게 비교할 수 있습니다. 일반적인 상황에서 줄 중 하나를 대문자로 쓰면 비교 결과는 거짓이 됩니다.
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JAVARUSH - ЛУЧШИЙ САЙТ ДЛЯ ИЗУЧЕНИЯ JAVA!");
       System.out.println(s1.equals(s2));
   }
}
콘솔 출력:

false
이 경우 클래스에는 String메소드가 있습니다 equalsIgnoreCase(). 비교에서 가장 중요한 것이 대소문자가 아닌 특정 문자의 순서인 경우 이를 사용할 수 있습니다. 예를 들어, 이는 두 이메일 주소를 비교할 때 유용합니다.
public class Main {

   public static void main(String[] args) {

       String address1 = "Moscow, Academician Korolev street, 12";
       String address2 = new String("Г. МОСКВА, УЛ. АКАДЕМИКА КОРОЛЕВА, ДОМ 12");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
이 경우에는 동일한 주소에 대해 이야기하고 있는 것이 분명하므로 이 방법을 사용하는 것이 equalsIgnoreCase()올바른 결정이 될 것입니다.

String.intern() 메서드

이 클래스에는 String또 다른 까다로운 방법이 있습니다 intern(). 이 방법은 'om' intern()과 직접적으로 작동합니다 String Pool. intern()문자열에 대해 메소드를 호출하면 다음이 수행됩니다.
  • 문자열 풀에 이 텍스트가 포함된 문자열이 있는지 확인합니다.
  • 있는 경우 풀에 해당 링크를 반환합니다.
  • 그렇지 않은 경우 문자열 풀에 이 텍스트가 포함된 줄을 배치하고 이에 대한 링크를 반환합니다.
new 를 intern()통해 생성된 문자열 참조에 메서드를 적용하면 . String Pool==
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2.intern());
   }
}
콘솔 출력:

true
이전에는 을 사용하지 않고 비교했을 때 intern()결과가 false였습니다. 이제 메소드는 "JavaRush - Java 학습을 위한 최고의 사이트!"라는intern() 텍스트가 있는 줄이 있는지 확인했습니다. 스트링 풀에서. 물론 거기에 있습니다. 우리가 글을 쓸 때 그것을 만들었습니다.
String s1 = "JavaRush is the best site to learn Java!";
s1메소드에 의해 반환된 참조와 참조가 메모리 의 동일한 영역을 가리키는 지 확인되었으며 s2.intern()물론 그렇습니다. :) 요약하고 기억하고 사용하는 주요 규칙은 다음과 같습니다. 문자열을 비교하려면 항상 equals()를 사용하세요. 방법! 문자열을 비교할 때 참조, 메모리 영역 등이 아닌 텍스트를 비교하는 것을 의미하는 경우가 거의 대부분입니다. equals() 메소드는 정확히 필요한 작업을 수행합니다. 다음은 스스로 공부할 수 있는 몇 가지 링크입니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION