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.