Instanceof Vs getClass()
Я вижу выигрыш в производительности при использовании операторов 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
?
Ответы
Ответ 1
Причина, по которой производительность instanceof
и getClass() == ...
различна, заключается в том, что они выполняют разные вещи.
-
instanceof
проверяет, является ли ссылка объекта в левой части (LHS) экземпляром типа в правой части (RHS) или некоторым подтипом.
-
getClass() == ...
проверяет, идентичны ли типы.
Поэтому рекомендуется игнорировать проблему производительности и использовать альтернативу, которая дает вам ответ, который вам нужен.
И да, чрезмерное использование любого из них - "дизайнерский запах". Если вы не будете осторожны, вы получите проект, в котором добавление новых подклассов приведет к значительному переделке кода. В большинстве случаев предпочтительным подходом является использование полиморфизма.
(Есть исключения. Классический в реализации equals(Object)
, в котором вам нужно проверить тип аргумента и вернуть false
, если он не соответствует. case, вам обычно нужно использовать getClass()
для правильного выполнения контракта equals
перед лицом подклассов.)
Ответ 2
Вы хотите точно соответствовать классу, например. только соответствие FileInputStream
вместо любого подкласса FileInputStream
? Если это так, используйте getClass()
и ==
. Обычно я делаю это в equals
, так что экземпляр X не считается равным экземпляру подкласса X, иначе вы можете столкнуться с трудными проблемами с симметрией. С другой стороны, это более полезно для сравнения двух объектов одного класса, чем одного конкретного класса.
В противном случае используйте instanceof
. Обратите внимание, что с getClass()
вам нужно будет убедиться, что у вас есть ненулевая ссылка для начала, или вы получите NullPointerException
, тогда как instanceof
просто вернет false
, если первый операнд имеет значение null.
Лично я бы сказал, что instanceof
более идиоматично, но в большинстве случаев использование любого из них в целом является запахом дизайна.
Ответ 3
Я знаю, что прошло некоторое время с тех пор, как это было задано, но вчера я узнал альтернативный вариант
Мы все знаем, что вы можете сделать:
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())
}
Ответ 4
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 ");
}
}
}
Выходы:
SubClass расширяет ParentClass. subClassInstance - экземпляр класса ParentClass.
Различные getClass() возвращают результаты с помощью subClassInstance и parentClassInstance.