I want to know how to identify subclasses at run time in java. In my program I am calling a method that returns a superclass object. The object can be an instance of any one of its sub-classes. I want to know the object is instance of which sub-class at run-time so that I can cast it to that subclass and access subclass methods. Can anyone help me in this?
Thanks
You can just use instanceof to check if an object is an instance of a particular class. eg:
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.meow();
} else if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark();
}
However, overuse of instanceof (or down-casting, for that matter) is generally considered to be a sign of poor design. It's better to instead make use of polymorphism. For example, have a (possibly abstract) "speak" method in Animal, and then each subclass would have a different implementation. The above code would then be replaced with a call to speak:
animal.speak();
Call getClass() on the object to access a Class object that tells you the object's actual type. You can then compare this to the ".class" static member of any class.
if (obj.getClass().equals(Foo.class)) { ... }
However many people would say what you're suggesting is bad design. Make sure it's necessary and consider alternatives. It's often necessary in implementing methods like equals().
Use instanceof operator. Like this
Superclass aSup = ...;
if(aSup instanceof Subclass) {
Subclass aSub = (Subclass) aSup;
aSub.subclass_method(...);
}
Note, instanceof is true if the object is a type assignable to the
class specified. The following (as described above) would work
if (o instanceof Cat.class) {
// ..
} else if (o instanceof Dog.class) {
// ..
} else {
throw IllegalArgumentException("Unexpected type");
}
However if you introduce a new subclass of cat, e.g. Tiger then the
first clause above would be triggered unless you updated all the code
that did this.
You may want to search for Double Dispatch for a potential way of
having to do the above, of course without knowing teh problem you are
trying to solve this may not be applicable.
You can use 'instanceof' operator and direct Class objects comparison as was mentioned above.
However, if you want to modify the code in order to avoid explicit checks I see two ways to go:
GoF Visitor pattern;
encapsulate class-specific processing logic, i.e. create something like this:
interface Handler<T> {
void handle(T object);
}
Map<Class<?>, Handler<?>> HANDLERS = /* init handlers mappings */;
...
public void process(Object obj) {
Handler<?> handler = HANDLERS.get(obj.getClass());
if (handler == null) {
throw new IllegalStateException("bla-bla-bla, no handler is registered for class " + obj.getClass());
}
handler.handle(obj);
}
You can use the instanceof operator to test the type an object and then cast.
Related
I want to know if Vector is holding <String> or <Integer>.
my function public void printVector(Vector <?> v){
I tried if(v instanceof <String>) but the compiler won't allow it.
whats the issue?
A code example that may be relevant:
import java.util.Iterator;
import java.util.Vector;
public class Cool {
public static void main(String[] args) {
Vector<Integer> v;
v = new Vector<>(5);
v.add(Integer.valueOf(5));
test(v);
}
private static void test(Vector<?> v) {
Iterator<?> iterator = v.iterator();
if (iterator.hasNext()) {
System.out.println(iterator.next().getClass());
}
}
}
This will print out class java.lang.Integer.
Your "test" method will have to check the type against a set of superclasses you're interested in (Employee/Customer/etc).
Also, Using vectors is generally considered bad practice in java.
Theoretically, you cannot know, because of type erasure. Basically, it means that you cannot get the generic type of the vector at runtime.
Now, in a real application, if you know that every objects are of the same type, you can get the first one and check its type with instanceof.
Note : this is not a good practice. Avoid that if you can. And as said by the others, you should consider other collections than Vector.
Note : as a rule of thumb, using instanceof is a clue of design flaw. Also, this is a costly operation.
If there is no first element, then your array is empty so you can just drop it.
As has been pointed out, Java's type erasure will make the compile-time generic type information unavailable run-time.
A common workaround for this is to pass the Class of the generic parameter as a method argument. This way you can then check whether the method was indeed passed a list of Customers or Employees:
public void print(List<?> list, Class<?> clazz) {
if (clazz == Employee.class) {
// ...
} else if (clazz == Customer.class) {
// ...
} else {
// ...
}
}
You could then call the method as follows:
Vector<Employee> legacy = new Vector<>();
// do stuff
print(legacy, Employee.class);
Note that resorting to instanceof or class checks is usually a sign of bad object oriented design and in general, you can achieve a more elegant solution through polymorphism, i.e. overriding the print() method for different object types -- or having a single print() method that utilizes different toString() implementations of the domain objects.
Suppose that I have these two objects:
Color c = new Color();
Shape s = new Shape();
and a method run() with some signature.
Now suppose that I want to call the run method sometimes with an object color and sometimes with an object shape. I could do something like these:
run(c);
public void( Color c){
//a bunch of code
}
or something like these:
run(s);
public void( Shape s){
//a bunch of code
}
As you can see, this is a bad solution because I'm creating the same method again but with different signatures and repeating a bunch of code 2 times. Is there any way to pass a generic object do this run method and then work with it? And of course no repeating code?
All objects in java extend (at the end) java.lang.Object class.
So, if you want a "generic" method, you should write something like:
public void methodName(Object o) {
...
}
But, make sure to make a casting accordingly inside this method.
You can use something like:
if (o instanceof Shape) {
Shape s = (Shape) o;
} else if (o instanceof Color) {
Color c = (Color) o
}
There are other options, for example passing an interface as a parameter of the method, and both classes should implement that interface.
Yes, you can use the Object class.
Every object has inheritance from the Object class, which means every object is a member of the object class.
If your method signature asks for an Object, then any object will be valid.
public void( Object o) {
// some code
}
Both shape and color are objects, so both will fit this method signature.
You have two options:
1. create a common interface of the objects and define the function with it:
public void run(CommonInterface c)
2. Accept Object as a parameter:
public void run(Object o)
The question that is asked is inviting very specific answers. As others have noted, if there is an interface that both objects can implement, that is the best approach. One can accept an Object as a parameter, and then (potentially) ascertain the type. However, this question is slightly problematic because it is not describing the actual desired result. It is the XY problem.
What happens when one then has a Texture object? Adjusting the code to continually deal with new types that do not implement a common interface will drive the maintenance costs very high. Therefore, one needs to look at the overall design. More than likely, the solution is that the run() should be implemented on each Object, and not be a method that takes the various object types directly.
As much as I do not really like the book, the maintenance example presented by this question is well described in Head First Object-Oriented Analysis and Design.
I think what matters here is what it is you want to do in // A bunch of code. For example, if you want to call .toString() method of Object, then you can pass object, but if you wish to do more than that, then you need to be more specific.
I think below example will be able to help you.
interface I {}
class A implements I {}
class B implements I {}
class Demo{
public static void main(String []args){
Demo d=new Demo();
d.run(new A());
d.run(new B());
}
public <T extends I> void run(T t){
// TODO do here you logic
}
}
Suppose I have a collection which stores generic types, e.g.
public class MyCollection<T> {
public T getNext()
{
//Remove T from list
//Return T
}
}
I am using this collection to store subtypes, e.g.
public class NormalPerson extends Human {
public void beNice() { }
}
public class Murderer extends Human {
public void kill() { }
}
...
MyCollection<Human> people = new MyCollection<>();
people.add(new NormalPerson());
people.add(new Murderer());
I would like to call methods specific to each subtype. e.g.
Human person = people.getNext();
switch(person.getType()) {
case NORMAL:
person.beNice(); //Symbol not found
break;
case MURDERER:
person.kill(); //Symbol not found
break;
}
However I can't unless I cast, e.g.
switch(people.getNext().getType()) {
case NORMAL:
NormalPerson person = (NormalPerson)people.getNext();
person.beNice();
break;
Is casting the only way to have this work? Am I going about this the wrong way?
Thanks
If you want a Human to be able to do both actions, you need to declare this in Human.
A simpler approach is to have a generic act method which cause a Person to be nice and a murder to kill. This way the caller doesn't need to know what action the Human will take.
Compiler can only understand reference type. So that when you write Human, compiler will try to look for the method in the Human class which it will not be able to find as it is actually something else which implements Human and the method that is trying to be called is not in the Human itself.
What you can do is you can use instanceof operator to check what type of the object it actually is otherwise casting is the only way to go.
For e.g.
Human h=new Killer();
if(h instanceof Killer)
{
(Killer)h.kill();
}
Hope this helps.
You are going about it in the wrong way. The calling code shouldn't check or even care about the exact type of the object, it should be enough to know that it is s ome kind of Human.
A common way to solve this is to have a more generic name for the method, maybe Human#doAction(), and let each class extending Human define its specialized behavior by overriding that method. This way you can call the same method no matter which Human you have, which greatly simplifies your code.
This question already has answers here:
How to determine an object's class?
(13 answers)
Closed 9 years ago.
Is there an easy way to verify that an object belongs to a given class? For example, I could do
if(a.getClass() = (new MyClass()).getClass())
{
//do something
}
but this requires instantiating a new object on the fly each time, only to discard it. Is there a better way to check that "a" belongs to the class "MyClass"?
The instanceof keyword, as described by the other answers, is usually what you would want.
Keep in mind that instanceof will return true for superclasses as well.
If you want to see if an object is a direct instance of a class, you could compare the class. You can get the class object of an instance via getClass(). And you can statically access a specific class via ClassName.class.
So for example:
if (a.getClass() == X.class) {
// do something
}
In the above example, the condition is true if a is an instance of X, but not if a is an instance of a subclass of X.
In comparison:
if (a instanceof X) {
// do something
}
In the instanceof example, the condition is true if a is an instance of X, or if a is an instance of a subclass of X.
Most of the time, instanceof is right.
If you ever need to do this dynamically, you can use the following:
boolean isInstance(Object object, Class<?> type) {
return type.isInstance(object);
}
You can get an instance of java.lang.Class by calling the instance method Object::getClass on any object (returns the Class which that object is an instance of), or you can use class literals (for example, String.class, List.class, int[].class). There are other ways as well, through the reflection API (which Class itself is the entry point for).
Use the instanceof operator:
if(a instanceof MyClass)
{
//do something
}
I agree with the use of instanceof already mentioned.
An additional benefit of using instanceof is that when used with a null reference instanceof of will return false, while a.getClass() would throw a NullPointerException.
Try operator instanceof.
The usual way would be:
if (a instanceof A)
However, there are cases when you can't do this, such as when A in a generic argument.
Due to Java's type erasure, the following won't compile:
<A> boolean someMethod(Object a) {
if (a instanceof A)
...
}
and the following won't work (and will produce an unchecked cast warning):
<A> void someMethod(Object a) {
try {
A casted = (A)a;
} catch (ClassCastException e) {
...
}
}
You can't cast to A at runtime, because at runtime, A is essentially Object.
The solutions to such cases is to use a Class instead of the generic argument:
void someMethod(Object a, Class<A> aClass) {
if (aClass.isInstance(a)) {
A casted = aClass.cast(a);
...
}
}
You can then call the method as:
someMethod(myInstance, MyClass.class);
someMethod(myInstance, OtherClass.class);
Say I have 3 classes like so:
class A {}
class B extends A {}
class C extends A {}
Would it then be possible to determine whether a particular object was an instance of A, B, or C?
I thought that something like this might work:
if (myObject.getClass().isInstance(B.class)) {
// do something for B
} else (myObject.getClass().isInstance(C.class)) {
// do something for C
} else {
// do something for A
}
but after reading a little I think it would always evaluate as B since it's just testing if a cast would work and there's no substantial differences between them.
The simpler and faster code is:
if (myObject instanceof B) {
} else if (myObject instanceof C) {
} else if (myObject instanceof A) {
}
Note that the order is important: you have to have the test for A last, as that will succeed for instances of B and C as well.
However, your original code would nearly work. Class.isInstance checks whether the value really is an instance of the given class or any superclass. So if myObject is an instance of C, then B.class.isInstance(myObject) will return false. All you've got wrong is that you're calling getClass() on myObject unnecessarily, instead of using B.class etc.
This is the approach you would take if you didn't know which classes you were interested in at compile time - the instanceof operator only works when you can specify the type statically in code.
Now if you want to find out whether myObject is an instance of exactly B (and not a subclass) then just use:
if (myObject.getClass() == B.class)
(This will blow up if myObject is a null reference, of course.)
Do this:
if (myObject instanceof B) {
// do something for B
} else (myObject instanceof C) {
// do something for C
} else {
// do something for A
}
You also might want to look at the double dispatch idiom which is an OO way of changing behaviour based on the type of an argument in languages which don't support multi-methods.
There is the instanceof operator that does what you want, as others have answered.
But beware that if you need something like this, it's a sign that there might be a flaw in the design of your program. The better, more object oriented way to do this is by using polymorphism: put a method in the superclass A, override that method in B and C, and call the method on myObject (which should have type A):
A myObject = ...; // wherever you get this from
// Override someMethod in class B and C to do the things that are
// specific to those classes
myObject.someMethod();
instanceof is ugly and should be avoided as much as possible, just like casting is ugly, potentially unsafe and should be avoided.
you could do this
if (myObject.getClass() == B.class) {
// do something for B (not subclasses of b!!!)
} else if(myObject.getClass() == C.class) {
// do something for C (not subclasses of c!!!)
} else if(myobject.getClass() == A.class) {
// do something for A (not subclasses of A!!)
} else if(myobjects instanceof A){
//all other subclasses of A
}