2010-03-09 3 views
56

В андроиде тестово приложения люкс У меня есть класс, как это, где B является мнением:Как проверить, является ли подкласс экземпляром класса во время выполнения?

public class A extends B { 
... etc... 
} 

теперь у меня есть список просмотр объектов, которые могут содержать A объектов, но в данном случае я только заботиться, если они» re подклассы или "экземпляры" B. Я хотел бы сделать что-то вроде:

ArrayList<View> viewList = getViews(); 
Iterator<View> iterator = viewList.iterator(); 
while (iterator.hasNext() && viewList != null) { 
    View view = iterator.next(); 
    if (view.getClass().isInstance(B.class)) { 
     // this is an instance of B 
    } 
} 

Проблема заключается в том, что, когда if встречает A объект не вычисляется на «экземпляр B». Есть ли способ сделать isSubclassOf или что-то в этом роде?

+1

если viewList массив пустой, то ваша программа падает, даже проверить в то время не поможет. – Tim

+2

От Effective C++ от Scott Meyers: «В любое время, когда вы обнаруживаете, что пишете код формы», если объект имеет тип T1, а затем что-то делать, но если он имеет тип T2, тогда сделайте что-нибудь еще », удалите себя. вместо использования переопределенного метода? Или, возможно, что-то вроде шаблона посетителя. – ishmeister

+1

Это для тестового примера, поэтому код на самом деле не находится в производственном приложении, это проверка, чтобы убедиться, что все использует правильные классы :) – iamamused

ответ

136

Вы должны внимательно прочитать API для этих методов. Иногда вы можете легко запутаться.

Это либо:

if (B.class.isInstance(view)) 

API говорит: Определяет, будет ли заданный объект(параметр) является назначение совместимым с объекта, представленного этого класса(Класс объекта, который вы являются вызовом метода в)

или:

if (B.class.isAssignableFrom(view.getClass())) 

API, говорит: Определяет, если класс или интерфейс, представленный этим класса объекта либо такой же, как, или суперкласс или суперинтерфейс, класс или интерфейс, представленный указанный параметр класса

или (без отражения и рекомендовать один):

if (view instanceof B) 
+9

+1 для if (view instanceof B). Простой и работает. –

+10

Обратите внимание, что 'instanceof' не будет работать для дженериков из-за стирания. – Qix

+1

@Qix Спасибо за информацию. Стирания - боль в более чем одной части тела, но работа без Generics хуже. – Hardcoded

21
if(view instanceof B) 

Это возвращает истину, если вид является экземпляром B или подкласса А (или любого подкласса B по этому вопросу).

+2

Я хотел бы упомянуть, что B должен быть импортирован в текущий .java-файл, чтобы это работало. Eclipse будет обозначать строку как имеющую ошибку, но не предлагая никаких полезных решений в противном случае (потратил впустую почти час, пытаясь разного синтаксиса, прежде чем осознать, что я просто не импортировал файл класса.) Для кого-то интересно, правильный синтаксис - это ((имя экземпляра) instanceof (имя класса)). Th Класс слова не отображается нигде в нем. – ArtOfWarfare

8

Может быть, я что-то отсутствует, но будет это не хватай:

if (view instanceof B) { 
    // this view is an instance of B 
} 
-1

Я никогда не использовал это, но попробовать view.getClass().getGenericSuperclass()

+1

Метод плохо назван и задокументирован. Это не поможет с проблемой, поскольку ни у A, ни у B нет никаких дженериков. – Hardcoded

6

Class.isAssignableFrom() - работает и для интерфейсов. Если вы этого не хотите, вам нужно позвонить getSuperclass() и протестировать, пока не достигнете Object.

+0

Это, похоже, работает, спасибо. – iamamused

0

Если есть полиморфизм, такие как проверка SQLRecoverableException против SQLException, это может быть сделано, как это.

try { 
    // sth may throw exception 
    .... 
} catch (Exception e) { 
    if(SQLException.class.isAssignableFrom(e.getCause().getClass())) 
    { 
     // do sth 
     System.out.println("SQLException occurs!"); 
    } 
} 

Просто сказать,

ChildClass child= new ChildClass(); 
if(ParentClass.class.isAssignableFrom(child.getClass())) 
{ 
    // do sth 
    ... 
} 
+1

Не делайте что-то вроде catching Exception и проверяйте класс исключения, если у вас нет ДЕЙСТВИТЕЛЬНО хорошей причины для этого. : '} catch (SQLException e) { } catch (исключение e) { }' – Hardcoded