instanceof Vs getClass () - PullRequest
       12

instanceof Vs getClass ()

103 голосов
/ 14 февраля 2011

Я вижу увеличение производительности при использовании операторов getClass() и == над оператором instanceOf.

Object  str = new Integer("2000");

long starttime = System.nanoTime();

if(str instanceof String) {
    System.out.println("its string");
} else {
    if (str instanceof Integer) {
        System.out.println("its integer");

    }
}

System.out.println((System.nanoTime()-starttime));

starttime = System.nanoTime();

if(str.getClass() == String.class) {
    System.out.println("its string in equals");
} else {
    if(str.getClass() == Integer.class) {
        System.out.println("its integer");
    }
}

System.out.println((System.nanoTime()-starttime));

Есть ли какое-либо руководство, какое из них использовать getClass() или instanceOf?

Учитывая сценарий: я знаю точные классы для сопоставления, то есть String, Integer (это конечные классы) и т. Д.

Использует оператор instanceOf, плохая практика

Ответы [ 4 ]

128 голосов
/ 14 февраля 2011

Причина, по которой производительность instanceof и getClass() == ... отличается, заключается в том, что они делают разные вещи.

  • instanceof проверяет, является ли ссылка на объект с левой стороны (LHS) экземпляром типа с правой стороны (RHS) или некоторого подтипа .

  • getClass() == ... проверяет идентичность типов.

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

И да, чрезмерное использование любого из них может быть "дизайнерским запахом". Если вы не будете осторожны, вы получите схему, в которой добавление новых подклассов приводит к значительной переработке кода. В большинстве ситуаций предпочтительным подходом является использование полиморфизма.

Бывают случаи, когда это не «дизайнерский запах». Например, в equals(Object) вам нужно проверить фактический тип аргумента и вернуть false, если он не совпадает. Лучше всего это сделать с помощью getClass().

39 голосов
/ 14 февраля 2011

Хотите ли вы соответствовать классу точно , например, соответствовать только FileInputStream вместо любого подкласса FileInputStream?Если это так, используйте getClass() и ==.Обычно я делаю это в equals, так что экземпляр X не считается равным экземпляру подкласса X - в противном случае вы можете столкнуться с хитрыми проблемами симметрии.С другой стороны, это более полезно для сравнения того, что два объекта относятся к классу того же , чем к одному конкретному классу.

В противном случае используйте instanceof.Обратите внимание, что с getClass() вам нужно будет убедиться, что у вас есть ненулевая ссылка для начала, или вы получите NullPointerException, тогда как instanceof просто вернет false, если первый операнд будет нулевым.

Лично я бы сказал, что instanceof более идиоматичен, но использование или из них в большинстве случаев является запахом дизайна.

18 голосов
/ 27 сентября 2012

Я знаю, что прошло много времени с тех пор, как об этом спросили, но вчера я узнал альтернативу

Мы все знаем, что вы можете сделать:

if(o instanceof String) {   // etc

а что если вы не знаете точно, какой это должен быть класс? вы не можете сделать в общем:

if(o instanceof <Class variable>.getClass()) {   

, поскольку это дает ошибку компиляции.
Вместо этого здесь есть альтернатива - isAssignableFrom ()

Например:

public static boolean isASubClass(Class classTypeWeWant, Object objectWeHave) {

    return classTypeWeWant.isAssignableFrom(objectWeHave.getClass())
}
2 голосов
/ 17 мая 2016

getClass () имеет ограничение на то, что объекты равны только другим объектам того же класса, того же типа времени выполнения, как показано в выходных данных кода ниже:

class ParentClass{
}
public class SubClass extends ParentClass{
    public static void main(String []args){
        ParentClass parentClassInstance = new ParentClass();
        SubClass subClassInstance = new SubClass();
        if(subClassInstance instanceof ParentClass){
            System.out.println("SubClass extends ParentClass. subClassInstance is instanceof ParentClass");
        }
        if(subClassInstance.getClass() != parentClassInstance.getClass()){
            System.out.println("Different getClass() return results with subClassInstance and parentClassInstance ");
        }
    }
}

Выходы:

Подкласс расширяет ParentClass.subClassInstance является экземпляром ParentClass.

Различные getClass () возвращают результаты с subClassInstance и parentClassInstance.

...