instanceof против getClass()

Я вижу прирост производительности при использовании getClass() и == оператор over 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 ответов


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

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

  • getClass() == ... проверяет, идентичны ли типы.

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

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

(есть исключения. Классический - в реализации equals(Object), в котором вам нужно проверить тип аргумента, и возвращение false если это не соответствует. В этом конкретном случае вам обычно нужно использовать getClass() для реализации договора equals правильно перед лицом подклассов.)


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

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

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


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

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

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())
}

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 оператор instanceof.

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