Сравнение типов классов в Java
Я хочу сравнить тип класса в Java.
Я думал, что смогу сделать это:
class MyObject_1 {}
class MyObject_2 extends MyObject_1 {}
public boolean function(MyObject_1 obj) {
if(obj.getClass() == MyObject_2.class) System.out.println("true");
}
Я хотел сравнить в случае, если obj, переданный в функцию, был расширен из MyObject_1 или нет.
Но это не работает. Похоже, что метод getClass() и .class предоставляет различный тип информации.
Как я могу сравнить два типа класса, не создавая другого фиктивного объекта, чтобы сравнить тип класса?
Ответы
Ответ 1
Попробуйте следующее:
MyObject obj = new MyObject();
if(obj instanceof MyObject){System.out.println("true");} //true
Из-за наследования это также верно для интерфейсов:
class Animal {}
class Dog extends Animal {}
Dog obj = new Dog();
Animal animal = new Dog();
if(obj instanceof Animal){System.out.println("true");} //true
if(animal instanceof Animal){System.out.println("true");} //true
if(animal instanceof Dog){System.out.println("true");} //true
Для дальнейшего чтения на instanceof: http://mindprod.com/jgloss/instanceof.html
Ответ 2
Если вы не хотите или не можете использовать instanceof
, сравните с equals
:
if(obj.getClass().equals(MyObject.class)) System.out.println("true");
BTW - странно, потому что два экземпляра Class
в вашем заявлении действительно должны быть одинаковыми, по крайней мере, в вашем примере кода. Они могут отличаться, если:
- классы имеют одно и то же короткое имя, но определяются в разных пакетах
- классы имеют одинаковое полное имя, но загружаются разными загрузчиками классов.
Ответ 3
Он печатает true
на моей машине. И это должно быть, иначе ничего в Java не будет работать так, как ожидалось. (Это объясняется в JLS: 4.3.4 Когда ссылочные типы одинаковы)
Есть ли у вас несколько загрузчиков классов?
Ah, и в ответ на этот комментарий:
Я понимаю, что у меня есть опечатка в моем вопрос. Я должен быть таким:
MyImplementedObject obj = new MyImplementedObject ();
if(obj.getClass() == MyObjectInterface.class) System.out.println("true");
MyImplementedObject реализует MyObjectInterface Итак, другими словами, я сравниваю его с его реализованным объекты.
ОК, если вы хотите проверить, что вы можете сделать это:
if(MyObjectInterface.class.isAssignableFrom(obj.getClass()))
или гораздо более кратким
if(obj instanceof MyobjectInterface)
Ответ 4
Как уже говорилось ранее, ваш код будет работать, если у вас нет одинаковых классов, загруженных на двух разных загрузчиках классов.
Это может произойти в случае, если вам потребуется несколько версий одного и того же класса в памяти одновременно, или вы делаете какие-то странные вещи для компиляции на лету (как и я).
В этом случае, если вы хотите рассматривать их как один и тот же класс (что может быть разумным в зависимости от случая), вы можете сопоставить их имена, чтобы сравнить их.
public static boolean areClassesQuiteTheSame(Class<?> c1, Class<?> c2) {
// TODO handle nulls maybe?
return c1.getCanonicalName().equals(c2.getCanonicalName());
}
Имейте в виду, что это сравнение будет делать то, что он делает: сравнить имена классов; Я не думаю, что вы сможете отбрасывать из одной версии класса в другую, и, прежде чем приступать к размышлению, вы можете убедиться, что есть веская причина для беспорядка загрузчика классов.
Ответ 5
Проверьте исходный код Class.java для equals()
public boolean equals(Object obj) {
return (this == obj);
}
Ответ 6
Хммм... Имейте в виду, что класс может или не может использовать equals() - это не требуется спецификацией. Например, HP Fortify будет отмечать myClass.equals(myOtherClass).
Ответ 7
Сравнение объекта с классом с использованием instanceOf
или... уже получено.
Если у вас есть два объекта и вы хотите сравнить их типы друг с другом, вы можете использовать:
if (obj1.getClass() == obj2.getClass()) {
// Both have the same type
}