백준 1100번 java string equals vs. ==

byeol·2022년 12월 30일
0
post-thumbnail

크게크게 먼저 보면
==는 주소값을 비교하고
equals는 데이터 값을 비교한다.

따라서

String st1 = "love";
String st2 = "love";

st1==st2 -> true
st1.equals(st2) -> true

String st1 = "love";
String st2 = new String("love");

st1==st2 -> false
st1.equals(st2) -> true

왜 이런 결과가 나올까?
String st1 = "love";
String st2 = "love";
여기서 st1과 st2는 멤버 변수이기 때문에 method영역에 저장되고
각 데이터는 Runtime Constant Pool이라는 것을 가지게 된다. 이는 각 데이터의 Reference를 가지고 있어서 실제 물리적 메모리 위치를 참조할 때 사용하게 된다. 이후, 실행 중에 중복되는 정보가 필요할 때에 기존의 정보를 사용한다. 따라서 "love" 중복되는 정보가 존재하여 같은 물리적 위치를 가지게 된다.

하지만
String st2 = new String("love");
는 참조형(Reference Type) 데이터 타입을 갖는 객체(인스턴스)이기 때문에 heap에 저장된다. 따라서 String st1= "love"와 다른 주소를 가지고 있다. 그래서 주소값을 비교하는 == 연산에서는 데이터 값이 같음에도 주소값이 다르기 때문에 false의 결과가 나오는 것이다.

결론적으로 String의 값을 비교할 때는 == 연산이 아닌 equals라는 메소드를 이용하도록 하자.

import java.util.*;


class Main{
 public static int solution(String[][] arr){
   int answer=0;
   for(int j=0;j<8;j+=2){
     for(int i=0;i<8;i+=2){
         if(arr[j][i].equals("F")) answer++;
      }
   }
   for(int j=1;j<8;j+=2){
     for(int i=1;i<8;i+=2){
         if(arr[j][i].equals("F")) answer++;
      }
   }
  return answer;
 } 
 public static void main(String[] args){
    Scanner kb = new Scanner(System.in);
    String[][] arr = new String[8][8];
    for(int i=0;i<8;i++){
         String k = kb.next();
         arr[i]=k.split("");
    }
 
   System.out.println(solution(arr));
  }
}

두개의 블로그를 참고하여 작성하였다.
매우매우 자세하고 이해가 잘되게 그림이 많아서 좋다 감사합니다.

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EB%B3%B4%EB%8A%94-%EC%9E%90%EB%B0%94-%EC%BD%94%EB%93%9C%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD%EC%8A%A4%ED%83%9D-%ED%9E%99
https://re-build.tistory.com/2

그렇다면 heap? method영역? 에 대한 정리를 해보도록 하자.

Java 프로그램은 JVM(자바 가상 머신)을 이용해서 메모리를 관리하는데 OS로부터 메모리를 할당받아 관리한다.

프로그램이 실행되면 용도에 따라서 알맞는 메모리 영역에 저장한다.
과정을 살펴보면
1. 프로그램을 실행하면 개발자가 작성한 코드 .java가 컴파일러(javac.exe)에 의해서 JVM이 읽을 수 있는 .class 파일로 변환
2. 기계가 읽을 수 있는 Byte Code인 .class 파일은 JVM 내부에 있는 Class Loader가 읽어들여 Runtime Data Area에 저장한다.
3. Runtime Data Area에 저장된 코드들은 Excution Engine이 하나의 명령어 단위로 읽어들여 프로그램을 실행
4. 사용이 끝난 코드은 Garage Collector가 모아서 메모리 해제

✔ Runtime Data Area(JVM의 메모리 영역)을 자세히 살펴보자

  • Method(Static) 영역
    JVM이 동작해서 클래스가 로딩될 때 생성
    JVM이 읽어들인 클래스와 인터페이스에 대한 런타임 상수풀, 멤버변수(인스턴스 변수와 클래스 변수), 상수, 생성자와 메소드 등을 저장하는 공간
    어느 곳에서나 접근 가능
    프로그램의 시작부터 종료가 될 때까지 메모리에 남아 있다. 따라서 무분별하게 많이 사용할 경우 메모리 부족 현상
    • 각 데이터는 Runtime Constant Pool이라는 것을 가지게 되는데 이는 각 데이터의 Reference를 가지고 있어서 실제 물리적 메모리 위치를 참조할 때 사용
      Constant Pool은 말 그래도 상수를 저장하는 공간이며 이외에도 필드나 메소드 등의 Reference 값들을 저장하고 있다. 이후, 실행중에 중복되는 정보가 필요할 때에 기존의 정보를 사용하도록 도와준다.

  • Stack 영역
    메소드 내에서 정의하는 기본 자료형인 지역변수의 데이터 값이 저장되는 공간
    메소드가 호출될 때 스택 영여에 스텍 프레임이 생기고 그 안에 메소드를 호출
    메소드가 종료되면 메모리에서 사라짐

    • 스텍 프레임 : 하나의 메서드당 하나의 스택 프레임이 필요하며 여기에 메서드의 매개변수, 지역변수, 리턴값 등이 저장된다.
  • Heap 영역
    JVM이 관리하는 프로그램 상엣 데이터를 저장하귀 위해 런타임 시 동적으로 할당하여 사용하는 영역
    참조형 데이터 타입을 갖는 객체, 배열 등이 저장되는 공간
    단, Heap영역에 있는 오브젝트들을 가리키는 레퍼런스 변수는 Stack에 적재
    Heap영역은 Stack 영역과 다르게 보관되는 메모리가 호출이 끝나더라도 삭제되지 않고 유지
    그러다 어떤 참조 변수도 Heap 영역에 있는 인스턴스를 참조하지 않게 된다면 가비지 컬렉터에 의해 메모리가 해제된다.
    stack은 쓰레드 개수마다 heap은 단 하나

profile
꾸준하게 Ready, Set, Go!

0개의 댓글