Есть ли способ определить, к какому типу относится экземпляр класса в Java? - PullRequest
1 голос
/ 11 сентября 2009

Скажем, у меня есть 3 класса, вот так:

class A {}
class B extends A {}
class C extends A {}

Тогда можно будет определить, был ли конкретный объект экземпляром A, B или C?

Я думал, что что-то подобное может сработать:

if (myObject.getClass().isInstance(B.class)) {
    // do something for B
} else (myObject.getClass().isInstance(C.class)) {
    // do something for C
} else {
    // do something for A
}

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

Ответы [ 5 ]

9 голосов
/ 11 сентября 2009

Более простой и быстрый код:

if (myObject instanceof B) {
} else if (myObject instanceof C) {
} else if (myObject instanceof A) {
}

Обратите внимание, что порядок важен: вам нужно пройти тест для A last, так как он будет успешным и для экземпляров B и C.

Однако ваш оригинальный код почти сработает. Class.isInstance проверяет, действительно ли значение является экземпляром данного класса или любого суперкласса. Так что если myObject является экземпляром C, то B.class.isInstance(myObject) вернет false. Все, что вы ошибаетесь, это то, что вы звоните getClass() на myObject без необходимости, вместо использования B.class и т. Д.

Это подход, который вы бы использовали, если бы вы не знали, какие классы вас интересовали во время компиляции - оператор instanceof работает только тогда, когда вы можете указать тип статически в коде.

Теперь, если вы хотите выяснить, является ли myObject экземпляром точно B (а не подклассом), просто используйте:

if (myObject.getClass() == B.class)

(Это взорвется, если myObject будет нулевой ссылкой, конечно.)

7 голосов
/ 11 сентября 2009

Сделайте это:

if (myObject instanceof B) {
    // do something for B
} else (myObject instanceof C) {
    // do something for C
} else {
    // do something for A
}
1 голос
/ 11 сентября 2009

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

0 голосов
/ 11 сентября 2009

вы могли бы сделать это

if (myObject.getClass() == B.class) {
    // do something for B (not subclasses of b!!!)
} else if(myObject.getClass() == C.class) {
    // do something for C (not subclasses of c!!!)
} else if(myobject.getClass() == A.class) {
    // do something for A (not subclasses of A!!)
} else if(myobjects instanceof A){
   //all other subclasses of A
}
0 голосов
/ 11 сентября 2009

Есть оператор instanceof, который делает то, что вы хотите, как и другие ответили.

Но учтите, что если вам нужно что-то подобное, это признак того, что в вашей программе может быть недостаток. Лучший, более объектно-ориентированный способ сделать это - использовать полиморфизм: поместить метод в суперкласс A, переопределить этот метод в B и C и вызвать метод myObject (который должен иметь тип A):

A myObject = ...;  // wherever you get this from

// Override someMethod in class B and C to do the things that are
// specific to those classes
myObject.someMethod();

instanceof ужасно, и его следует избегать, насколько это возможно, точно так же, как кастование уродливо, потенциально небезопасно и его следует избегать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...