==와 equals의 차이점은 무엇일까?
자바에서 객체비교를 할 때 자주 사용하는 것 중 == 연산자와 equals가 있다. 두 객체가 같은 객체인지 비교할 때 쓰는것인데, 쓰임새가 약간 다르다. == 은 두 객체의 주소값을 비교하는것이고, equals는 String객체의 실제 값을 비교하는것이다. 처음 듣고 이게 무슨말이지? 라고 생각할 수 있다.
자바에서는 객체를 생성할 때 메모리상에 생성을 하게 되는데, 그 방식이 2가지가 있다. 리터럴을 이용하는 방식과 new 연산자를 이용해 생성하는 방식이 있다.
String test1 = "test";
String test2 = new String("test");
test1이 리터럴, test2가 new 연산자로 객체를 생성한 방식이다. 두 객체의 실제 값은 test로 동일하지만, 다른게 있다. 바로 객체가 생성되는 위치인데 우선 둘 다 heap이라는 메모리내 공간에 생성된다. 하지만 test1처럼 리터럴로 생성시 heap내에 String constant pool이라는 곳에 생성되는데 쉽게 말해서 String이 존재하는 별도의 공간내에 생성된다. pool이라는 말처럼 수영장 같은 String을 위한 공간이 따로 존재하고 그 안에 "test"라는 값을 생성한다. test2처럼 new 연산자를 사용하면 객체를 생성하고 별도의 주소값(혹은 참조값)을 부여해 생성한다. 그리고 그 안에 "test"라는 값을 집어넣는다. 따라서 test1과는 값은 같지만, 위치가 다르다는것이다.
그렇다면 만약 아래처럼 생성하면 어떨까?
String test1 = "test";
String test2 = "test";
String test3 = new String("test");
String test4 = new String("test");
보시다시피 4개의 객체가 모두 "test"라는 동일한 값을 가지고 있다. test1과 test2는 리터럴 방식으로 생성했는데, 위에서 말한것처럼 String pool에 생성한다. 하지만 두개를 생성한것처럼 보이지만 실제로는 한개가 생성된 것이다. String pool에 test1이 "test"를 생성하고 test2는 생성전에 pool내에 "test"라는 값이 있는지 확인 후 만약 있다면 해당값을 참조만 하고 생성하지는 않고, 없다면 새로 생성한다. 따라서 test1과 test2는 완전히 같은 객체가 된다.
test3와 test4는 동일하게 "test"라는 값을 생성했지만, 주소값이 다르다. new로 생성하게되면 heap메모리안에 각각 다른 주소값(참조값)으로 생성되기 때문이다. 그래서 test3와 test4를 ==으로 비교하면 false가 나오고 equals로 비교해야만 true가 나온다.
String a = "test";
String b = "test";
String c = new String("test");
String d = new String("test");
System.out.println(a==b); //true
System.out.println(a==c); //false
System.out.println(c==d); //false
System.out.println(a.equals(c)); //true
System.out.println(c.equals(d)); //true