29

I have to compare a Class object against a list of pre-defined classes.

Is it safe to use == or should I use equals?

if        (klass == KlassA.class) {
} else if (klass == KlassB.class) {
} else if (klass == KlassC.class) {
} else {
}

Note: I cannot use instanceof, I don't have an object, I just have the Class object. I (mis)use it like an enum in this situation!

Lii
  • 11,553
  • 8
  • 64
  • 88
reto
  • 16,189
  • 7
  • 53
  • 67

6 Answers6

35

java.lang.Class does not override the equals method from java.lang.Object, which is implemented like this:

public boolean equals(Object obj) {
    return (this == obj);
}

So a == b is the same as a.equals(b) (except if a is null).

robinst
  • 30,027
  • 10
  • 102
  • 108
5

I am not sure if this will work for your specific situation, but you could try Class.isAssignableFrom(Class).

KlassA.class.isAssignableFrom(klass)
jt.
  • 7,625
  • 4
  • 27
  • 24
3

For the most of the Java applications this is correct. However, comparing Java classes using the operator == is safe just if both the classes are loaded by the same classloader.

Jonhnny Weslley
  • 1,080
  • 2
  • 13
  • 24
  • 5
    That shouldn't matter. Two classes with the same name but loaded by different class loaders will not have the same address nor will they be the same class. So `==` would be false and that would be correct. If the OP wanted to compare class names that would be different (and then use `klass.getName().equals(xxxx.class.getName())`. – Kevin Brock Apr 15 '10 at 20:50
3

As mentioned in previous answers, to compare objects of Class type (or java.lang.Class objects) we should use == operator. However, It may be a bit confusing because always the result of comparison between objects through == operator can not cause right results (we usually use equal() method). For example, the result of this expression is false:

new String("book") == new String("book")//false

The reason is that,

The virtual machine manages a unique Class object for each type. Therefore, you can use the == operator to compare java.lang.Class objects. From Core Java for the Impatient - Page 153

Therefore:

new String("book").getClass() == new String("book").getClass()//true

or

Class.forName("java.lang.String") == Class.forName("java.lang.String")//true

result in true.

MMKarami
  • 1,144
  • 11
  • 14
  • It's not strictly true that only one class will exist with a given name per virtual machine. Since ClassLoader is a part of Class object identity, several loaders which have concurrently loaded class with the same name will produce two classes that aren't equal. – M. Prokhorov Nov 24 '17 at 16:22
  • First, thanks for your comment. Your point is correct, according oracle doc: "A class is determined by its full name and the class loader". As I am sure you know, Class.forName(...) returns a Class object corresponding to a class package and name, which is located in caller or current class loader. As, classLoader.loadClass(className) is used for getting Class object to a special class loader. So, in current class loader we can use Class.forName(...) to comparison. – MMKarami Nov 24 '17 at 17:51
  • 4
    what I'm saying is - you indeed can compare result of several `Class.forName` calls in single expression, but if you save the `Class` object in a field somewhere and stored it, then it won't necessarily be always equal to results of later calls to `Class.forName` from different classloading contexts. This was a problem for several pretty big libraries in the past, which is why I felt like it should be mentioned. – M. Prokhorov Nov 26 '17 at 12:59
1

It's probably safe.

If the object doesn't override the Equals method it will make a comparison between the references. And if two variables point to the same object, their references match.

Paulo Santos
  • 11,285
  • 4
  • 39
  • 65
0

I prefer to use == for comparison between class objects and enum constants because it results in compilation time errors in case of incompatible types.

For example:

Class<?> cls1 = Void.class;
String cls2 = "java.lang.String";

if (cls1 == cls2) doSomething();        // Won't compile

if (cls1.equals(cls2)) doSomething();   // Will compile
polarfish
  • 85
  • 8