6

Как определить класс объекта?

25

У меня есть два класса: B и C, которые наследуются от класса A. Теперь у меня есть объект, который является экземпляром одного из этих классов — B или C. Как можно определить, к какому именно типу относится этот объект? Есть ли способ сделать это в языке программирования, который я использую?

5 ответ(ов)

9

Если объект obj является экземпляром класса C, то выполните следующий код:

if (obj instanceof C) {
    // ваш код
}
2

Несколько правильных ответов были представлены, но существуют и другие методы: Class.isAssignableFrom() и простой попытки привести объект к нужному типу (что может вызвать ClassCastException).

Резюме возможных способов

Давайте подытожим возможные способы проверки, является ли объект obj экземпляром типа C:

// Метод #1
if (obj instanceof C)
    ;

// Метод #2
if (C.class.isInstance(obj))
    ;

// Метод #3
if (C.class.isAssignableFrom(obj.getClass()))
    ;

// Метод #4
try {
    C c = (C) obj;
    // Если исключения нет: obj имеет тип C или он может быть NULL!
} catch (ClassCastException e) {
}

// Метод #5
try {
    C c = C.class.cast(obj);
    // Если исключения нет: obj имеет тип C или он может быть NULL!
} catch (ClassCastException e) {
}

Различия в обработке null

Существует различие в обработке null:

  • В первых двух методах выражения возвращают false, если obj равно null (то есть null не является экземпляром чего-либо).
  • Третий метод приведет к NullPointerException, если obj равно null.
  • Напротив, четвертый и пятый методы принимают null, так как null может быть приведен к любому типу!

Напомним: null не является экземпляром какого-либо типа, но его можно привести к любому типу.

Замечания

  • Class.getName() не следует использовать для выполнения теста на "является ли экземпляром" потому что, если объект не является типом C, а подклассом этого типа, он может иметь совершенно другое имя и пакет (поэтому имена классов, очевидно, не совпадут), но при этом он все еще будет считаться типом C.
  • По той же причине наследования Class.isAssignableFrom() не является сymmetric:

obj.getClass().isAssignableFrom(C.class) вернет false, если тип obj является подклассом C.

0

Вы можете использовать:

Object instance = new SomeClass();
instance.getClass().getName(); // вернет имя класса (в виде строки) (== "SomeClass")
instance.getClass(); // вернет объект класса SomeClass

Надеюсь, это поможет. Однако я думаю, что чаще всего не является хорошей практикой использовать это для управления потоком или что-то подобное...

0

Использование любых из предложенных методов считается "ароматом кода", что указывает на плохой объектно-ориентированный дизайн.

Если ваш дизайн хорош, вам не потребуется использовать getClass() или instanceof.

Любой из предложенных методов вполне сгодится, но это стоит учитывать с точки зрения дизайна.

0

В данном случае мы можем использовать рефлексию для получения имени класса объекта.

Пример кода:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String name = request.getClass().getName();
}

В результате выполнения этого кода вы получите имя класса объекта, который передается в переменную-ссылку HttpServletRequest. Это может быть полезно для отладки или логирования, чтобы узнать, какой именно класс был использован в данном контексте.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь