HOWTO · Java

Java에서 객체 유형 가져 오기

이 기사에서는 Java에서 객체 유형을 가져 오는 방법에 대해 설명합니다.

이 페이지의 내용

API나 구현을 직접 확인할 수 없는 클래스에서 객체를 받으면, 참조 변수만으로는 실제 구체 타입을 알기 어려울 수 있습니다. Java에서는 두 가지 유용한 검사를 제공합니다. getClass()는 정확한 런타임 클래스를 반환하고, instanceof는 객체를 지정한 타입으로 다룰 수 있는지 검사합니다. 정확히 같은 클래스인지 알아야 하는지, 해당 클래스와 하위 클래스까지 호환되는지 확인해야 하는지에 따라 선택하세요.

getClass()로 객체의 정확한 런타임 클래스 가져오기

null이 아닌 모든 Java 객체는 Object에서 getClass()를 상속합니다. 이 메서드는 객체의 정확한 런타임 클래스를 나타내는 Class 객체를 반환합니다. 반환된 결과를 Integer.class 같은 클래스 리터럴과 비교하면 됩니다. 래퍼 클래스에는 이 검사에 사용할 별도의 class 필드가 없습니다.

다음 완전한 프로그램은 정수 래퍼를 Object 참조에 저장한 다음, 런타임 클래스를 두 클래스 리터럴과 비교합니다. 실행 결과를 보면 객체의 정확한 클래스는 Integer이고 Number는 아닙니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

public class ObjectType {
  public static void main(String[] args) {
    Object value = Integer.valueOf("15");

    System.out.println(value.getClass() == Integer.class);
    System.out.println(value.getClass() == Number.class);
    System.out.println(value.getClass().getName());
  }
}
true
false
java.lang.Integer

첫 번째 비교가 참인 이유는 객체의 런타임 클래스가 Integer이기 때문입니다. Integer가 Number를 상속하더라도 두 번째 비교는 거짓입니다. getClass()의 동등성 비교에는 상위 클래스가 포함되지 않습니다. 문자열 표현이 필요하면 getClass().getName()으로 클래스의 정규화된 이름을 얻을 수 있습니다. null 참조에서 이 메서드를 호출하면 NullPointerException이 발생하므로, 참조가 없을 수 있다면 먼저 null인지 확인하세요. 예제 코드와 출력은 원문 그대로 유지되어 출력 메시지는 영어로 표시됩니다.

instanceof로 객체가 클래스에 해당하는지 검사하기

Java의 instanceof 연산자를 사용하면 null이 아닌 객체가 지정된 클래스 또는 그 하위 클래스의 인스턴스인지 검사할 수 있습니다. 결과는 불리언 값이므로 캐스팅하거나 타입별 처리를 선택하기 전에 유용하게 사용할 수 있습니다. 이 키워드는 소문자로 쓰며 객체 참조와 검사할 타입 사이에 놓습니다.

일반적인 Object 참조로 받은 객체를 검사하는 완전한 예제를 실행해 보세요.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

public class ObjectType {
  public static void main(String[] args) {
    Object value = Double.valueOf("10");

    if (value instanceof Number) {
      System.out.println("value is a Number");
    }
    if (value instanceof Double) {
      System.out.println("value is a Double");
    }
    if (value instanceof Integer) {
      System.out.println("value is an Integer");
    }
  }
}
value is a Number
value is a Double

여기서는 Number와 Double 검사가 일치하고, Integer 검사는 일치하지 않습니다. getClass()를 호출하는 경우와 달리, null 참조에 instanceof를 적용하면 false가 됩니다. 따라서 null일 가능성이 있는 값의 타입을 검사할 때 안전하게 사용할 수 있지만, 누락된 값을 처리하기 위해 프로그램에 필요한 별도 로직까지 대신하지는 않습니다. 예제 코드와 출력은 원문 그대로 유지되어 출력 메시지는 영어로 표시됩니다.

getClass()와 instanceof 중 선택하기

객체의 정확한 구현 클래스가 중요하다면 value.getClass() == SomeType.class를 사용하세요. 하위 클래스를 포함해 호환되는 구현이면 충분하다면 value instanceof SomeType을 사용하세요. 예를 들어 모든 Number를 받는 처리기는 일반적으로 instanceof Number로 검사하면 됩니다. 반면 Integer를 다른 숫자 래퍼와 구별해야 하는 작업이라면 정확한 클래스를 비교할 수 있습니다.

null에 대한 동작도 다릅니다. instanceof는 null에 대해 false를 반환하지만, getClass()는 객체에서 호출해야 하므로 참조가 null이면 NullPointerException이 발생합니다. 애플리케이션에서 null이 별도의 의미를 가진다면 정확한 클래스 검사를 하기 전에 명시적으로 확인하세요.

사용자 정의 클래스 계층에서 객체 검사하기

간단한 상속 계층을 사용하면 두 검사의 차이를 분명히 볼 수 있습니다. 이 예제에서 Specialist는 Employee를 상속합니다. 참조 변수는 Employee로 선언되어 있지만 실제 객체는 Specialist입니다. 따라서 선언된 타입과 런타임 클래스는 서로 다른 질문에 답합니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

public class ObjectType {
  public static void main(String[] args) {
    Employee employee = new Specialist();

    System.out.println(employee.getClass() == Specialist.class);
    System.out.println(employee.getClass() == Employee.class);
    System.out.println(employee instanceof Employee);
    System.out.println(employee instanceof Specialist);
  }
}

class Employee {}

class Specialist extends Employee {}
true
false
true
true

정확한 클래스 비교 결과는 Specialist이며, Specialist가 Employee를 상속한다는 이유만으로 Employee를 반환하지는 않습니다. 객체가 Specialist이면서 동시에 Employee이기도 하므로 instanceof 검사는 둘 다 일치합니다. 실무에서는 런타임 클래스로 구체 클래스를 확인하고, instanceof로 객체의 타입이 계층 구조에서 기대하는 부분에 해당하는지 검사하면 됩니다. 예제 코드와 출력은 원문 그대로 유지되어 출력 메시지는 영어로 표시됩니다.