자바에는 instanceof 연산자가 있습니다. 무엇일까요?

 


 String 클래스의 equals 메서드를 보겠습니다.

 

 anObject는 Object 객체를 참조하는 변수입니다.

 

 

 980번째 줄을 보면, anObject instanceOf String 이라고 되어 있습니다. anObject가 String 인스턴스인지 확인하겠다는 것입니다. 그런데 왜 하필? 일단, 우리는 anObject가 Object 참조형이라는 것을 볼 필요가 있는데요. Object는 최상위 루트 부모입니다.

 

 

 그러면, String도 Object를 상속받은 거고, MyObj1도 Object를 상속받은 것이라고 할 수 있어요. 그러면 String은 Object라고 할 수 있나요?

 

 

 네 맞습니다. 그러면 반대로, Object 인스턴스는 String이라고 할 수 있을까요?

 

 

 그것은 아닙니다. 왜냐하면, String일 수도 있지만, ArrayList<?>일 수도 있고, Vector <?>일 수도 있고, 아니면 내가 정의한 MyObj일 수도 있기 때문입니다. 이제 아래 코드를 보겠습니다.

 

 

 아래 코드는 굉장히 간단한 코드입니다. new String("ME")는 새로운 string 인스턴스를 생성합니다. 그리고 그것을 Object 참조형인 o가 가리키고 있어요. 이것은 가능합니다. 왜냐하면, Object를 상속받은 것이 String이기 때문입니다. 그림으로 그려보면 아래와 같습니다.

 

 

 여기서 질문. o.indexOf('a'); 를 호출하면 어떨까요? o는 Object를 참조하는 참조 변수이고, indexOf는 Object에 정의되어 있는 메서드가 아닙니다. 따라서 컴파일 오류가 뜹니다.

 

 

 이건 어떨까요? equals는 String에서 오버라이딩 메소드입니다. 그러면 어떤 equals를 호출할지는 컴파일 타임이 아니라, 실행 시간에 결정을 하겠네요. 저는 o의 equals를 호출할 건데요. o는 사실 String 인스턴스를 가리키는 모양새입니다. 그러면 문자열 클래스의 오버라이딩 된 equals를 호출할 건데요. 정말 그런지 타고 들어가 보겠습니다.

 

 

 정말 그렇네요. 동적 바인딩이랑 정적 바인딩 정도는 짚고 넘어가시는 게 좋겠습니다.

 

 

 이제 다시 이 부분을 보겠습니다. o는 String 인스턴스를 가리키고 있는 Object 참조 변수였습니다. 이것을 Integer 참조형으로 변환한다면 어떨까요?

 

 

 ClassCastException이 뜹니다. java.lang.String이 java.lang.Integer로 cast가 될 수 없다는 뜻입니다. 이는 String 입장에서 보았을 때, Integer는 아무 것도 아니기 때문입니다.

 

 

 아무런 관계도 없어요. String은 Integer로도 변환이 될 수 없고, 역변환도 마찬가지입니다.

 


 Object 참조형이 매개변수로 들어왔을 때를 생각해 봅시다. 특히 equals는 Object 참조형을 받습니다. 그러면 이것이 String을 가리키는지, Integer를 가리키는지, 아니면 Short를 가리키는지 모릅니다. 그런데 상식적으로 String에서 동등성을 판단하는데, Integer라던지, Short가 인자로 들어오면 이상한 그림이 그려집니다.

 

 "abc"를 담고 있는 String과 3이라는 걸 담고 있는 Integer를 비교하면 이상하지 않을까요?

 

 

980번째 줄의 anObject instanceof String이 그러한 역할을 수행합니다. anObject가 실제로 String 인스턴스를 가리키고 있지 않으면, false를 돌려줍니다.

 

 

 정말 그런지 디버그를 돌려보겠습니다. 일단 저는 equals의 인자로, Integer 인스턴스를 넘겨주었습니다.

 

 

 o는 Object 참조형이지만, 실제로는 String 인스턴스를 가리키고 있고, equals가 오버라이딩이 되었으므로, String의 equals가 call이 될 겁니다. 980번째 줄에 걸려 있군요. anObject가 String의 인스턴스냐?

 

 

 아니기 때문에 바로 false를 리턴하는 995번째 줄로 갑니다.

 

 

 다음 프로그램을 보겠습니다. o는 String 인스턴스입니다. 그러면 이것은 Object 인스턴스일까요? 이것은 개는 동물이냐고 묻는 질문과 같습니다. 당연하게도, 개는 동물이므로 true입니다. 이것은 equals를 구현할 때 골치가 아플 수도 있는 문제인데, 이 부분에 대한 것은 나중에 차근 차근 보도록 하겠습니다. 그러면 o는 String의 instance일까요? 이것은 개는 개냐라고 묻는 것과 같습니다. 당연히 참입니다.

 

 

 

 당연하게도 둘 다 true가 출력됩니다. equals는 Object 참조값을 인자로 받습니다. 그리고 각각의 객체에 대해서 equals를 오버라이딩을 할 때, instanceOf가 들어가는 경우가 있는데요. Object가 들어왔을 때, String끼리 비교를 한다고 되어 있는데, Integer가 떡하니 들어왔다면, 그리고 그것이 String인지 검사를 하지 않아서, compare 알고리즘이 수행된다면, 이상한 상황이 발생할 수도 있기 때문입니다.