How to get the object class in Java? - java

What is the best way to get the class of an instance ?
What is the recommended way ? and what are the differences (performances) between :
Compare the class
if( this.getClass().equals(MyClass.class) ){
which seems to be the same as this.getClass() == MyClass.class (or perhaps using Class.forName("com.test.MyClass"))
Test the instance of (seems to be the more readable)
if( this instanceof MyClass ){
Test the instance using class
if( MyClass.class.isInstance(myInst) ){

I would recommend this.getClass().equals( MyClass.class) when you want to match a class exactly because "someString" instanceOf Object will produce true because String class is subtype of Object.
This is checking is a relationship between any instance and the class.
In your case any subclass of MyClass will produce true
instanceof tests whether the thing on the left is an instance of the type on the right or some subtype.
getClass() == ...tests whether the types are identical.

Option one only tells you if the class is exactly what you are testing. This is usually not very useful. For example, it's completely pointless for interfaces. If this is actually what you want to do, you can probably use == unless you're messing around with different ClassLoaders, in which case there may be more than one instance of each Class object.
Option two tells you whether the object is statically assignable to the given class (i.e. can be cast to it).
Option three does the same as two, but using the reflection API. You'll only need this if you're doing dynamic typing. The built-in instanceof is more readable and should be much more efficient.

Related

Using instanceof to seperate classes in an ArrayList

apologies if this is simple or has been answered before, I'm new to Java and in my research I can't find too much on this issue and have not yet found a solution.
I have an ArrayList with multiple classes that all share a common Interface, in this example the interface is called "Packable". I'm trying to create a method that takes a class parameter and sweeps through each element of this ArrayList, returning a new list containing all the items in the original list that are of the same class as the reference parameter.
This is my code so far, trying the instanceof method:
public List<Packable> getOfType(Packable reference){
List<Packable> typeOfItems = new ArrayList<>();
for (Packable item: itemsStored) {
if (item instanceof reference){
typeOfItems.add(item);
}
}
return typeOfItems;
}
This is throwing an error as it doesn't yet recognise reference as a class. This question mentions a method isAssignableFrom with the answer stating: "When using instanceof, you need to know the class of B at compile time. When using isAssignableFrom() it can be dynamic and change during runtime." (Thanks Marc Novakowski)
I understand that given the parameter the class isn't known at compilation and as such I've tried implementing isAssignableFrom and can't really seem to get it to work. The IDE doesn't really recognise or suggest it, and there isn't too much about the method online. I've tried implementing it the way the JavaDocs suggest but this isn't working either:
if (reference.isAssignableFrom(item.getClass())){
typeOfItems.add(item);
}
Any help or advice on methods to look into would be greatly appreciated. Thanks for reading the question, and again apologies if this is simple or has been answered elsewhere and I've just missed it. Thanks everyone
I'm not sure what Packable is, but you appear to be confused about a few concepts here.
In java, Packable reference does not represent the Packable concept. It represents a specific instance of Packable (or null).
In other words, given Dog dog, that means dog is some specific dog. Not 'the general concept of a dog'. We know that the specific animal that dog is referring to is, at least, a Dog. It could be Fifi, the neighbour's schnauzer.
instanceof, on the other hand, is about the general concept of things: if (fifi instanceof Dog) is how you're supposed to use it. You're more or less attempting to do the equivalent of if (fifi instanceof rover) which just doesn't make sense. How can one dog be 'an instance' of another? It's not that the answer is 'true' or 'false', but that the very question doesn't even make sense, which is why javac doesn't compile it. It has no idea what this even means.
Java, being java, makes objects of many things. Notably including the very notion of things. Thus, there is the class java.lang.Class, instances of which represent classes. A bit of alice-going-down-the-rabbit-hole thing is happening here: Classes as a concept are also represented as instances of the java.lang.Class class.
A class OBJECT (so, an instance of java.lang.Class) has the .isAssignableFrom method. This in fact takes another j.l.CLass as argument, it's for checking if one type is a subtype of another. In that sense, the question linked is needlessly confusing - you're really looking for the instanceOf method (there is an instanceof language construct, but the j.l.Class class has an isInstance method, which is unrelated, other than that they roughly accomplish the same goal: Check if some INSTANCE is of a type that is equal to, or a subtype of, some TYPE.
This is an example of how to use it:
Class<?> c = Number.class;
Object o = Integer.valueOf(5);
System.out.println(c.isInstance(o));
this is more or less equivalent to:
Object o = Integer.valueOf(5);
System.out.println(o instanceof Number);
Except now the Number part no longer needs to be written at 'write the code' time, you can supply it, say, read it from a parameter. You'd have to, of course, dynamically construct the Class instance. You can do so either by string-lookup, or by getting the actual type of an actual object. For example:
String input = scanner.next(); // user types in "java.lang.Number"
Class<?> c = Class.forName(input);
Object o = Integer.valueOf(5);
System.out.println(c.isInstance(o));
Or:
Object i = Integer.valueOf(5);
Object d = Double.valueOf(10);
Class<?> c = i.getClass(); // will be java.lang.Integer.class
System.out.println(c.isInstance(d)); // false
But doing this latter bit is really dangerous. Often i.getClass() returns some hidden impl detail subtype (java is hierarchical and object oriented, anywhere, say, an ArrayList is needed, someone is free to make a new class: class MyVariantOfArrayList extends ArrayList, and use that - now you write ArrayList foo = getList(), but foo.getClass() doesn't return ArrayList - no, you invoke that method on the object the foo variable points at, so, it'd be MyVariantOfArrayList.class, not ArrayList.class.
It's possible Packable itself represents a type. But then it either needs to also have isInstance and isAssignableFrom and such (and you need to start questioning why you're badly reinventing the wheel here - java.lang.Class already exists!), or it needs a .getRepresentedClass() method. You can't call it .getClass(), as the JVM has already given all objects that method, and it would return Packable.class itself.

Could someone explain me the .getClass() method in java

I am currently taking a java class in university. This is my first programming class and I've stumbled on something that I just cannot understand. As i learned, there are two ways of comparing variables. The first is using the ==, !=, <, > , =< , >= signs for PRIMITIVE variables such as int,double,etc. and the second way is to use the .equals() method for reference type. Now here is my question:
When I use the .getClass() method, I can compare two classes with the .equals() method and the == / != method. Since I can use the ==/!= signs, I'd suppose that the .getClass() method which returns the class of an object must return a primitive type. But searching on google the only thing I found out about this method in the java API is that it returns the class of an object. It doesn't tell me the variable type it returns. How exactly does this method work. What does it return? I tried to ask my teacher but she didn't know. Thank you!
You first need to know how == and != compare the two operands. The reason why == and != cannot be used to compare reference types is that they actually compare the memory addresses of the two reference type variables.
So if I have two strings:
String x = "Hello";
String y = x;
Since x and y share the same memory address after the second line is executed, x == y evaluates to true.
The same goes for the getClass() method. The getClass() method returns the class of the object as a Class<T> object. The question is, why this evaluates to true:
x.getClass() == y.getClass()
The answer is simple. Because x and y are both of type String. So calling getClass will return the same instance. This means the two returned the objects share the same memory address.
"But when I compare strings with the same characters with the == operator, it evaluates to false!" you shouted.
This is because the strings are located at different memory addresses. But the classes that getClass will return is always at the same memory address if the class that they represent is the same. This is due to the way ClassLoader works. But I'm not an expert that.
You just need to know that the objects returned by getClass is at the same memory address if the classes they represent are the same.
The comparators == and != compare equality in the way of identity. So how this works for primitives is obvious. However it can also be used to compare objects. However most often this does not work as expected. There are some exceptions:
Strings are stored as literals, therefore if you define two instances of String containing the same value, they use the same literal. Think of this like both instances pointing to the same memory location.
Enums are basically a collection of constants, therefore an enum value is either the same instance or it is not. It cannot be that the enum has the same value but is another instance.
The same is true for Class objects, which is what you get when calling getClass(). A Class object is created by the ClassLoader the first time it is the *.class file is loaded. On subsequent calls the same Class object is used. Therefore Class objects may be compared with == and !=. However beware that if A.class is loaded by two different ClassLoaders, the class objects that you get returned from them are not of the same instance.
getClass() returns an instance (object) of the Class class. Since each Java class has a single instance of the Class class, if two objects belong to the same class, getClass() for those two objects will return the same isntance and therefore you can use == for comparing them, since == when applied to reference types determines if the two references refer to the same instance.
The .getClass method will just return the class of the object. When you declare a new instance of an object, it will be referring to a class. There can only be one class per jvm but multiple object referring to it. So when you get the class of two objects, they might be referring to the same class!
polymorphism is one of the most important feature for java. for example:
//this shows one use of getclass method.
public class Main {
public static void main(String[] args) {
Main m = new Main();
Animal animal = new Animal();
Human human = new Human();
m.dosomething(animal);//print animal
m.dosomething(human);//print human
}
private void dosomething(Animal an){
System.out.println(an.getClass().toString());
}
}
class Human extends Animal{
private void dance(){
}
}
class Animal{
private void eat(){
}
}

How does inheritance work with for-each loops?

How does inheritance work in relation to a for-each loop? Imagine I have two classes: SubClass and SuperClass, and I have the following ArrayList.
/**
* Containes both SuperClass and SubClass instances.
*/
ArrayList<SuperClass> superClasses = new ArrayList<SuperClass>();
Is it possible to iterate over superClasses in such a way as to only select subClasses.
The following:
for(SubClass subClass : superClasses){
// Do Foo
}
does not do this.
The following is the only thing that I could get to work:
for(SuperClass superClass : superClasses){
if(superClass instanceof SubClass){
// Do Foo
}
}
However I do not want to use instanceof unless absolutely necessary, as I keep reading everywhere (StackOverflow, Oracle Tutorials etc) that one can almost always find a better solution that increases encapsulation. Is there a more elegant way of doing this?
Well you could write a helper method to hide the instanceof test... Guava has a method like this, for example, in Iterables.filter, which you could use like this:
for (SubClass subclass : Iterables.filter(superclasses, SubClass.class)) {
...
}
It's only moving the instanceof check though really - it's not getting rid of it. Fundamentally you need that check, because something's got to do the filtering.
The first approach (for (SubClass subClass : superClasses)) cannot work as the compiler cannot ensure that there are only objects of tyoe SubClass in there.
In Java (without external libraries) it is not possible to preselect on the Class. Therefore the instanceof is the normal way to do this.
instanceof would work absolutely fine in this situation. But if you really do have reasons for not using it you could always give the superclass some variable, Boolean skipMe = true, and change that to false in the subclass if you wanted.
But I suggest using instanceof
I recommend to manage a separate List which only contains instances of SubClass, if possible.

Java reflection, what class does the object have?

im trying to do some reflection on a applet.
things i found are some arrays of ints, strings, objects etc.
for example, if there was a field with an object[] and object[0].toString() = [I#7593c366
then i know its an integer array. but what if it says aa#98324ca33 is it's class then aa?
im using a classloader, so my first guess when i see this i need to load the aa class (part before the #, and use the object in it. but im not sure the part befor the # is the class. can somebody say me this is right? or got other ideas?
thnx!
You shouldn't use toString() for this - for one thing, it can have been overridden. As a straightforward example:
Object x = "aa#98324ca33";
String bogusClassName = x.toString();
You would clearly be wrong to think that x refers to an object of type aa here - it refers to a string.
You can find out the class of any object just by calling getClass() on it:
Object x = new SomeType();
Class<?> clazz = x.getClass();
It's not really clear what you're trying to do or where you're getting information from in the first place, but you definitely shouldn't be using toString to determine the class involved.
Yes, the part before # is the class fqn, but you should not rely on that. Object can override toString() and then your logic will fail.
Use obj.getClass() instead.
Take a look at the class java.lang.Class. Just call getClass on an object to retrieve its class instead of using the toString method
Object anObject = ... ;
Class<?> clazz = anObject.getClass();
If you want to check whether it is an array, you can use to Class#isArray() method
clazz.isArray()
The other way around is also possible. If you have a Class instance, you can determine whether an object belongs to this class by using the Class#isInstance( Object ) method
clazz.isInstance( anObject );

Any reason to prefer getClass() over instanceof when generating .equals()?

I'm using Eclipse to generate .equals() and .hashCode(), and there is an option labeled "Use 'instanceof' to compare types". The default is for this option to be unchecked and use .getClass() to compare types. Is there any reason I should prefer .getClass() over instanceof?
Without using instanceof:
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Using instanceof:
if (obj == null)
return false;
if (!(obj instanceof MyClass))
return false;
I usually check the instanceof option, and then go in and remove the "if (obj == null)" check. (It is redundant since null objects will always fail instanceof.) Is there any reason that's a bad idea?
Josh Bloch favors your approach:
The reason that I favor the instanceof approach is that when you use the getClass approach, you have the restriction that objects are only equal to other objects of the same class, the same run time type. If you extend a class and add a couple of innocuous methods to it, then check to see whether some object of the subclass is equal to an object of the super class, even if the objects are equal in all important aspects, you will get the surprising answer that they aren't equal. In fact, this violates a strict interpretation of the Liskov substitution principle, and can lead to very surprising behavior. In Java, it's particularly important because most of the collections (HashTable, etc.) are based on the equals method. If you put a member of the super class in a hash table as the key and then look it up using a subclass instance, you won't find it, because they are not equal.
See also this SO answer.
Effective Java chapter 3 also covers this.
If you use instanceof, making your equals implementation final will preserve the symmetry contract of the method: x.equals(y) == y.equals(x). If final seems restrictive, carefully examine your notion of object equivalence to make sure that your overriding implementations fully maintain the contract established by the Object class.
What I'm trying to get at here is that if you believe getClass() is the only reliable way to preserve symmetry, you are probably using equals() the wrong way.
Sure, it's easy to use getClass() to preserve the symmetry required of equals(), but only because x.equals(y) and y.equals(x) are always false. Liskov substitutability would encourage you to find a symmetry-preserving implementation that can yield true when it makes sense. If a subclass has a radically different notion of equality, is it really a subclass?
The reason to use getClass is to ensure the symmetric property of the equals contract. From equals' JavaDocs:
It is symmetric: for any non-null
reference values x and y, x.equals(y)
should return true if and only if
y.equals(x) returns true.
By using instanceof, it's possible to not be symmetric. Consider the example:
Dog extends Animal.
Animal's equals does an instanceof check of Animal.
Dog's equals does an instanceof check of Dog.
Give Animal a and Dog d (with other fields the same):
a.equals(d) --> true
d.equals(a) --> false
This violates the symmetric property.
To strictly follow equal's contract, symmetry must be ensured, and thus the class needs to be the same.
Angelika Langers Secrets of equals gets into that with a long and detailed discussion for a few common and well-known examples, including by Josh Bloch and Barbara Liskov, discovering a couple of problems in most of them. She also gets into the instanceof vs getClass. Some quote from it
Conclusions
Having dissected the four arbitrarily chosen examples of implementations of equals() , what do we conclude?
First of all: there are two substantially different ways of performing the check for type match in an implementation of equals() . A class can allow mixed-type comparison between super- and subclass objects by means of the instanceof operator, or a class can treat objects of different type as non-equal by means of the getClass() test. The examples above illustrated nicely that implementations of equals() using getClass() are generally more robust than those implementations using instanceof .
The instanceof test is correct only for final classes or if at least method equals() is final in a superclass. The latter essentially implies that no subclass must extend the superclass's state, but can only add functionality or fields that are irrelevant for the object's state and behavior, such as transient or static fields.
Implementations using the getClass() test on the other hand always comply to the equals() contract; they are correct and robust. They are, however, semantically very different from implementations that use the instanceof test. Implementations using getClass() do not allow comparison of sub- with superclass objects, not even when the subclass does not add any fields and would not even want to override equals() . Such a "trivial" class extension would for instance be the addition of a debug-print method in a subclass defined for exactly this "trivial" purpose. If the superclass prohibits mixed-type comparison via the getClass() check, then the trivial extension would not be comparable to its superclass. Whether or not this is a problem fully depends on the semantics of the class and the purpose of the extension.
This is something of a religious debate. Both approaches have their problems.
Use instanceof and you can never add significant members to subclasses.
Use getClass and you violate the Liskov substitution principle.
Bloch has another relevant piece of advice in Effective Java Second Edition:
Item 17: Design and document for inheritance or prohibit it
Correct me if I am wrong, but getClass() will be useful when you want to make sure your instance is NOT a subclass of the class you are comparing with. If you use instanceof in that situation you can NOT know that because:
class A { }
class B extends A { }
Object oA = new A();
Object oB = new B();
oA instanceof A => true
oA instanceof B => false
oB instanceof A => true // <================ HERE
oB instanceof B => true
oA.getClass().equals(A.class) => true
oA.getClass().equals(B.class) => false
oB.getClass().equals(A.class) => false // <===============HERE
oB.getClass().equals(B.class) => true
If you want to ensure only that class will match then use getClass() ==. If you want to match subclasses then instanceof is needed.
Also, instanceof will not match against a null but is safe to compare against a null. So you don't have to null check it.
if ( ! (obj instanceof MyClass) ) { return false; }
It depends if you consider if a subclass of a given class is equals to its parent.
class LastName
{
(...)
}
class FamilyName
extends LastName
{
(..)
}
here I would use 'instanceof', because I want a LastName to be compared to FamilyName
class Organism
{
}
class Gorilla extends Organism
{
}
here I would use 'getClass', because the class already says that the two instances are not equivalent.
instanceof works for instences of the same class or its subclasses
You can use it to test if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface.
ArryaList and RoleList are both instanceof List
While
getClass() == o.getClass() will be true only if both objects ( this and o ) belongs to exactly the same class.
So depending on what you need to compare you could use one or the other.
If your logic is: "One objects is equals to other only if they are both the same class" you should go for the "equals", which I think is most of the cases.
Both methods have their problems.
If the subclass changes the identity, then you need to compare their actual classes. Otherwise, you violate the symmetric property. For instance, different types of Persons should not be considered equivalent, even if they have the same name.
However, some subclasses don't change identity and these need to use instanceof. For instance, if we have a bunch of immutable Shape objects, then a Rectangle with length and width of 1 should be equal to the unit Square.
In practice, I think the former case is more likely to be true. Usually, subclassing is a fundamental part of your identity and being exactly like your parent except you can do one little thing does not make you equal.
Actually instanceof check where an object belongs to some hierarchy or not. ex: Car object belongs to Vehical class. So "new Car() instance of Vehical" returns true. And "new Car().getClass().equals(Vehical.class)" return false, though Car object belongs to Vehical class but it's categorized as a separate type.

Categories