아래와 같이 사용자로부터 숫자와 연산자를 입력받고 그에 맞게 계산하는 간단한 계산기 프로그램을 만들려고 했다.
import java.util.Scanner;
public class Equals {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
String op = scanner.next();
int b = scanner.nextInt();
if (op=="+"){
System.out.println(a+b);
} else {
System.out.println("넘어가지네?");
}
}
}

코드를 실행하여 3 + 4 를 입력 했을 때, if문으로 가지지 않고 계속 else문으로 넘어갔다. 이에 관하여 간단하게 정리해 보려고 한다.
자바에서 문자열은 String이라는 타입을 사용하고, 위에서 연산자(op)를 문자열(String)로 입력받았다. 하지만, String은 데이터 타입이 아니라 엄연히 말하면 클래스라는 것을 알게 됐다.
- 기본 자료형처럼 직접 할당하는 방법
String b = "min82";위와 같이 직접 할당 한 경우에는 String pool이란 곳에 "min82"가 저장되고 저장된 주소를 b에 할당한다.
- 참조형처럼 생성자를 통한 방법
String a = new String("min82");
Case 1️⃣
String A = "min82"; String B = "min82";A와 B 모두 같은 문자열을 할당 받았다. 이때 B는 String pool에 새로운 값을 생성하지 않고 A가 가리키고 있는 주소를 가리키게 된다. 즉, A와 B는 같은 주소 값을 갖게 된다.
Case 2️⃣
String a = new String("min82"); String b = "min82";a는 heap이라는 메모리 영역에 인스턴스가 생성되고 "min82"라는 값을 가지고 있다. 하지만, b는 String pool 안에 있는 메모리에 "min82"를 만들고 그 메모리 주소를 가리키고 있다.
즉, 데이터 값이 같더라도 주소 값은 다르게 된다. 따라서 문자(열) 비교시에는 ==(주소 값 비교연산자)가 아닌 equals(String클래스 메소드)를 사용해야 한다.
다시 코드로 돌아가봤을 때
String op = scanner.next();
scanner.next()로 입력받게 되면 참조형처럼 값을 할당하게 된다. + 기호를 입력하게 되면 아래 처럼 입력받게 되는 것이다.
String op = new String("+");
이렇게 새로운 "+"의 주소가 생성되고, if문의 판정문에는 주소 비교연산자(==)가 사용됐기 때문에 데이터 값이 같아도 다른 주소를 갖게 되어 if문의 판정이 성립되지 않았던 것이다.
== 와 equals()의 가장 큰 차이점은 == 연산자는 비교하고자 하는 두개의 대상의 주소값을 비교하는데 반해 String 클래스의 equals() 메소드는 비교하고자 하는 두 개의 대상의 데이터 값 자체를 비교한다는 것이다.
기본 타입의 int형, char형등은 Call by Value 형태로 기본적으로 대상에 주소값을 가지지 않는 형태로 사용된다. 하지만, String은 일반적인 타입이 아니라 클래스다. 클래스는 기본적으로 Call by Reference 형태로 생성 시 주소값이 부여되기 때문에 String 타입을 선언했을때는 같은 값을 부여하더라도 서로 간의 주소값이 다르게 된다.
Reference
https://coding-factory.tistory.com/536
https://limkydev.tistory.com/139