в чем разница между instanceof и getclass в java
Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 11
97. Выдвигаются ли условия переопределения соглашения при переопределении Equals?
согласованность — для любых значений x и y повторный вызов x.equals(y) будет всегда возвращать значение предыдущего вызова этого метода при условии, что поля, используемые для сравнения этих двух объектов, не были изменены между вызовами.
98. Что будет, если не переопределить Equals и HashCode?
99. Почему симметричность выполняется, только если x.equals (y) возвращает true?
100. Что такое коллизия в HashCode? Как с ней бороться?
101. Что будет, если элемент, участвующий в контракте с HashCode, изменит свое значение?
102. Напишите методы Equals and HashCode для класса Student, который состоит из полей String name и int age
Приведение объекта аргумента к одному типу (вдруг это был объект родительского типа).
Задание начального значения хеш-кода равным примитиву age объекта.
Умножение текущего хеш-кода на 31 (для большего разброса) и добавление к нему хеш-кода непримитивного строкового поля (если оно не null).
В результате такого переопределения хеш-кода объекты с одинаковыми значениями name и int всегда будут возвращать одно и тоже значение.
103. В чем разница применения if (obj instanceof Student) и if (getClass () == obj.getClass ())?
instanceof проверяет, является ли ссылка на объект с левой стороны экземпляром типа с правой стороны или некоторым его подтипом.
То есть, если getClass() проверяет полную идентичность класса, то instanceof вернет true даже если объект будет всего лишь подтипом, что может дать нам большую гибкость при активном использовании полиморфизма. Собственно, оба подхода хороши, если понимать особенности их работы и применять в нужных местах.
104. Дайте краткую характеристику метода clone ().
105. В чем заключается особенность работы метода clone () с полями объекта типа ссылки?
Exceptions
106. В чем разница между error и exception?
107. Какая разница между checked и unchecked, exception, throw, throws.
108. Какова иерархия исключений?
109. Что такое checked и unchecked exception?
Unchecked — исключения, которые обрабатывать не нужно, так как они не проверяются во время компиляции и, как правило, более непредсказуемые. То есть, основная разница с checked в том, что для них эти механизмы try — catch или пробрасывания работают также, но они не являются обязательными.
instanceof против getClass ()
4 ответа
Поэтому рекомендуется игнорировать проблему производительности и использовать альтернативу, которая дает вам ответ, который вам нужен.
Является ли использование оператора instanceOf плохой практикой?
Не обязательно. Чрезмерное использование instanceOf или getClass() может быть «дизайнерским запахом». Если вы не будете осторожны, вы получите проект, в котором добавление новых подклассов приведет к значительному изменению кода. В большинстве случаев предпочтительным подходом является использование полиморфизма.
Такие термины, как «передовой опыт», «плохая практика», «запах дизайна», «антипаттерн» и т. Д. Следует использовать осторожно и относиться к ним с подозрением. Они поощряют черно-белое мышление. Лучше делать свои суждения в контексте, а не основываться исключительно на догмах; например то, что кто-то сказал, является «лучшей практикой». Я рекомендую всем прочитать No Best Practices, если они еще этого не сделали.
GetClass () имеет ограничение, заключающееся в том, что объекты равны только другим объектам того же класса, того же типа времени выполнения, как показано в выходных данных приведенного ниже кода:
Различные getClass () возвращают результаты с subClassInstance и parentClassInstance.
Я знаю, что это было давно, но вчера я узнал альтернативу
Мы все знаем, что вы можете сделать:
Но что, если вы точно не знаете, какой это должен быть класс? вы не можете делать:
Лично я бы сказал, что instanceof более идиоматичен, но широкое использование любого из них в большинстве случаев является запахом дизайна.
Instanceof Vs getClass( )
The reason that the performance of instanceof and getClass() == … is different is that they are doing different things.
instanceof tests whether the object reference on the left-hand side (LHS) is an instance of the type on the right-hand side (RHS) or some subtype.
getClass() == … tests whether the types are identical.
So the ation is to the performance issue and use the alternative that gives you the answer that you need.
Not necessarily. Overuse of either instanceOf or getClass() may be «de smell». If you are not careful, you end up with a de where the addition of new subclasses results in a ificant amount of code reworking. In most situations, the preferred approach is to use polymorphism.
However, there are cases where these are NOT «de smell». For example, in equals(Object) you need to test the actual type of the argument, and return false if it doesn’t match. This is best done using getClass().
Terms like «best practice», «bad practice», «de smell», «antipattern» and so on should be used sparingly and treated with suspicion. They encourage black-or-white thinking. It is better to make your judgements in context, rather than based purely on dogma; e.g. something that someone said is «best practice». I that everyone read No Best Practices if they haven’t already done so.
answered Feb 14 ’11 at 7:44
Stephen CStephen C
641k8787 gold badges742742 silver badges11111111 bronze badges
Do you want to match a class exactly, e.g. only matching FileInputStream instead of any subclass of FileInputStream? If so, use getClass() and ==. I would typically do this in an equals, so that an instance of X isn’t deemed equal to an instance of a subclass of X — otherwise you can get into tricky symmetry problems. On the other hand, that’s more usually useful for comparing that two objects are of the same class than of one specific class.
Otherwise, use instanceof. Note that with getClass() you will need to ensure you have a non-null reference to start with, or you’ll get a NullPointerException, whereas instanceof will just return false if the first operand is null.
Personally I’d say instanceof is more idiomatic — but using either of them extensively is a de smell in most cases.
answered Feb 14 ’11 at 7:43
Jon SkeetJon Skeet
1.3m800800 gold badges87698769 silver badges89578957 bronze badges
I know it has been a while since this was asked, but I learned an alternative yesterday
We all know you can do:
if(o instanceof String) < // etc
but what if you dont know exactly what type of class it needs to be? you cannot generically do:
as it gives a compile error.
Instead, here is an alternative — isAsableFrom()
public ic boolean isASubClass(Class classTypeWeWant, Object objectWeHave)
answered Sep 26 ’12 at 20:55
Andy DingfelderAndy Dingfelder
1,85011 gold badge1717 silver badges2828 bronze badges
getClass() has the restriction that objects are only equal to other objects of the same class, the same run type, as illustrated in the output of below code:
SubClass extends ParentClass. subClassInstance is instanceof ParentClass.
Different getClass() return results with subClassInstance and parentClassInstance.
answered May 17 ’16 at 17:16
Saurav SahuSaurav Sahu
9,92555 gold badges4444 silver badges6666 bronze badges
Not the answer you’re looking for? Browse other questions tagged java class instanceof or ask your own question.
JavaNerd.
В этой статье мы рассмотрим методики сравнения объектов в Java и какие инструменты нам для этого понадобятся. Как вы сможете понять из этой статьи задача сравнения объектов не такая уж, и тривиальная и выработать единый и универсальный подход для сравнения всех объектов едва ли представляется возможным. Сравнение объектов в Java выполняется с помощью оператора сравнения == и метода equals(). Если оператор сравнения можно использовать с примитивами, то метод equals() используется только с экземплярами классов. При их использовании проверяется ссылаются ли переменные на один и тот же объект в памяти. Рассмотрим пример:
Object ob1 = new Object();
System.out.ln(ob1 == ob2); // true
Переменная ob1 содержит в себе ссылку на объект класса Object, а переменная ob2 просто ее копирует при объявлении, в итоге две переменных ссылаются на один и тот же объект в памяти, что при сравнении этих двух переменных всегда возвращается true. Другой пример:
Object ob1 = new Object();
Object ob2 = new Object();
System.out.ln(ob1 == ob2); // false
Теперь при объявлении каждой из переменных вызывается оператор new, который для каждой из них создает свой экземпляр класса Object, поэтому при сравнении этих двух переменных каждый раз возвращается false, потому что обе переменные указывают на разные объекты в разных участках памяти. Давайте теперь сравним что-то более конкретное, например, две строки:
String str1 = new String(«ABC»);
String str2 = new String(«ABC»);
System.out.ln(str1 == str2); // false
Как видите поведение метода equals() для класса String несколько отличается. Это происходит по одной простой причине, метод equals() определен в классе Object, поэтому все классы в Java его наследуют и вольны переопределять, что и было сделано в классе String. Как видите методом equals() проверяются на соответствие символы двух строк, если они совпадают, то метод возвращает true. Перед тем как приступить к переопределению метода equals() и комплексному сравнению объектов созданных нами классов, мы рассмотрим инструменты, которые нам для этого понадобятся: оператор instanceof и метод getClass().
Оператор instanceof.
Оператор instanceof служит для проверки к какому классу принадлежит объект. a instanceof B возвращает истину, если в переменной a содержится ссылка на экземпляр класса B, подкласс B (напрямую или косвенно, иначе говоря, состоит в иерархии наследования классов) или реализует интерфейс B (так же напрямую или косвенно). Давайте подробнее рассмотрим, как это работает на примере:
Иерархия классов очень проста, главный класс A, классы B и C от него наследуются. Посмотрим как поведет себя оператор instanceof с нашими классами:
System.out.ln( aB instanceof B ); //true
System.out.ln( aB instanceof A ); //true
System.out.ln( aB instanceof C ); //false
Первая проверка возвращает true, потому что aB является экземпляром класса B. Вторая проверка возвращает true, потому что aB является подклассом A. И последний вызов оператора instanceof возвращает false, несмотря на то, что оба класса B и С наследуются от A, это совершенно разные классы. На самом деле, ситуация с последним вызовом оператора instanceof сложнее, чем может показаться. Типом переменной aB является класс A, иначе говоря, она может содержать в себе любой из трех классов, в том числе класс C и компилятор это проверяет, если возникнет ситуация, при которой оператор instanceof не сможет ни при каких условиях вернуть true — возникнет ошибка компиляции:
System.out.ln( aB instanceof C ); //ошибка компиляции
Переменная с типом класса B на данном этапе нашей иерархии классов ни при каких условиях не может содержать в себе ссылку на класс С, поэтому возникает ошибка компиляции. Опять же, есть один нюанс, это правило не работает для интерфейсов:
System.out.ln( a instanceof I ); //false
Как мы видим связи между классом A и интерфейсом I нет никакой, и тем не менее ошибки компиляции не возникает, а оператор instanceof возвращает false. Всегда существует вероятность в будущем реализации интерфейса тем или иным классом, поэтому в данном случае компилятор идет нам уступки. Если же класс реализует интерфейс, то оператор instanceof вернут true:
class A implements I<>
System.out.ln( a instanceof I ); //true
Как упоминалось ранее все классы наследуются от класса Object либо напрямую, либо через родительский класс, поэтому a instanceof Object всегда будет возвращать true за исключение одной ситуации:
class A implements I<>
System.out.ln( a instanceof I ); //true
Так вот, a instanceof Object всегда будет возвращать true, только если a не равна null.
Метод getClass().
Метод getClass() возвращает класс объекта, содержащий сведения об объекте: public final Class getClass(). Как Вы можете заметить метод является конечным и переопределению не подлежит. С методом getClass() все обстоит несколько проще и очевидней нежели с оператором instanceof.
public class Example<
public ic void main(String… args)<
System.out.ln(a.getClass() == a1.getClass()); // true
System.out.ln(a.getClass() == b.getClass()); // false
System.out.ln(a.getClass() == ab.getClass()); // false
Как видите, метод прост и эффективен, ровно до тех пор, пока не применен механизм наследования. При наследовании этот метод становится менее полезным. Это утверждение может многим показаться спорным, но мы к нему еще вернемся в конце главы, когда будем размышлять о том, каким должен быть идеальный метод для сравнения объектов.
Метод equals().
Почему мы так подробно рассматривали оператор instanceof? Потому что это будет наша первая проверка, хотя многие предпочитают использовать метод getClass(), но обо всем по порядку. Как говорилось выше, метод equals() содержится в классе Object и наследуется всеми классами, в которых мы вправе его переопределить, давайте это сделаем:
public boolean equals(Object o)<
public ic void main(String[] args) <
В нашем примере метод equals() всегда будет возвращать true, что и было продемонстрировано. Не смотря на то, что в памяти было создано два объекта Eq, метод equals() все равно вернул истину. Единственное на что хотелось бы обратить внимание, это аннотация @Override. Она используется для явного обозначения переопределения метода, если бы мы допустили ошибку и просто перегрузили метод, то с этой аннотацией у нас бы возникла ошибка компиляции:
@Override // ошибка компиляции
public boolean equals(Eq l)<
В примере выше метод equals() перегружен (в качестве параметра методу передается класс Eq вместо Object), что и приводит к ошибке компиляции. Настало время рассмотреть более сложный пример:
What is the difference between instanceof and Class.isAssignableFrom(. )?
Which of the following is better?
The only difference that I know of is, when ‘a’ is null, the first returns false, while the second throws an exception. Other than that, do they always give the same result?
14 Answers 14
instanceof can only be used with reference types, not primitive types. isAssignableFrom() can be used with any class objects:
Talking in terms of performance :
TL;DR
Use isInstance or instanceof which have similar performance. isAssignableFrom is slightly slower.
Sorted by performance:
Based on a benchmark of 2000 iterations on JAVA 8 Windows x64, with 20 warmup iterations.
In theory
Using a soft like bytecode viewer we can translate each operator into bytecode.
Measuring how many bytecode instructions are used by each operator, we could expect instanceof and isInstance to be faster than isAssignableFrom. However, the actual performance is NOT determined by the bytecode but by the machine code (which is platform dependent). Let’s do a micro benchmark for each of the operators.
The benchmark
Credit: As advised by @aleksandr-dubinsky, and thanks to @yura for providing the base code, here is a JMH benchmark (see this tuning guide):
Gave the following results (score is a number of operations in a time unit, so the higher the score the better):
Warning
To give you an example, take the following loop:
Thanks to the JIT, the code is optimized at some point and we get:
Note
Originally this post was doing its own benchmark using a for loop in raw JAVA, which gave unreliable results as some optimization like Just In Time can eliminate the loop. So it was mostly measuring how long did the JIT compiler take to optimize the loop: see Performance test independent of the number of iterations for more details
Я думаю, почти любого Java разработчика когда-то спрашивали на собеседовании: «Какие есть методы у класса Object?»
Меня, по крайней мере, спрашивали неоднократно. И, если в первый раз это было неожиданностью (кажется, забыл про clone), то потом я был уверен, что уж методы Object’а-то я знаю;)
И каково же было мое удивление, когда спустя несколько лет разработки я наткнулся на собственное незнание сигнатуры метода getClass()
Итак, у нас есть класс А и объект этого класса a:
0. A.class vs a.getClass()
Начнем с простого. При вызове getClass() может отработать полиморфизм, и результатом будет класс-потомок.
Тут была ложь, на которую мне указали в комментариях. class — это не статическое поле, коим может показаться (и даже не нативное-псевдо-статическое поле, как думал я), а особая конструкция языка. И, в отличие от статического поля, обратиться к нему через объект нельзя!
Но это так, цветочки. Идем дальше.
1. А что такое этот ваш Class?
A.class — объект класса Class. Смотрим в Class.java:
Если подумать, то понятно зачем это нужно: теперь, в частности, можно написать метод, который возвращает произвольный тип, в зависимости от аргумента:
A.class возвращает объект класса Class:
2. А что же возвращает a.getClass()?
Собрав воедино все вышесказанное, можно догадаться, что:
Действительно, ввиду полиморфизма нужно не забывать, что фактический класс объекта a — не обязательно A — это может быть любой подкласс:
3. А что же написано в Object.java?
Все эти дженерики — это, конечно, замечательно, но как записать сигнатуру метода getClass синтаксисом java в классе Object?
А никак:
А на вопрос, почему не компилировался пример выше, ответит Максим Поташев джавадок к методу:
The actual result type is Class where |X| is the erasure of the static type of the expression on which getClass is called.