Reputation: 5784
I have the following class and interface:
public class BasicObject{...}
public interface CodeObject{...}
I want to create a method in which the argument needs to be of type BasicObject and implements CodeObject. I tried the following code but it doesn't guarantee clazz to be a class that implements CodeObject.
myMethod(Class<? extends BasicObject> clazz){...}
I want to do something like this but it doesn't compile:
myMethod(Class<? extends BasicObject implements CodeObject> clazz){...}
Upvotes: 79
Views: 130531
Reputation: 3224
Your pattern class has to extend BasicObject
and extend/implement CodeObject
(which is actually an interface). You can do it with multiple classes declared in the wildcard definition of the method signature, like this:
public <T extends BasicObject & CodeObject> void myMethod(Class<T> clazz)
Note that it won't work if you do it any of these ways:
public <T extends BasicObject, CodeObject> void myMethod(Class<T> clazz)
This is technically valid syntax, but CodeObject
is unused; the method will accept any classes that extends BasicObject
, no matter whether they extend/implement CodeObject
.
public void myMethod(Class<? extends BasicObject & CodeObject> clazz)
public void myMethod(Class<? extends BasicObject, CodeObject> clazz)
These are just wrong syntax according to Java.
Upvotes: 121
Reputation: 5570
There are two approaches to your problem depending on whether you want to pass a class type in your method argument that extends BasicObject
and implements CodeObject
or a class object that does so. There are solutions for both.
Solution 1:
If you want to pass the Class
itself, you can do this, as explained by @bontade,
public <R extends BasicObject & CodeObject> void myMethod(Class<R> clazz)
and if you want to pass class
object, you can write
public <R extends BasicObject & CodeObject> void myMethod(R clazz)
The above is the more complex way which deals with generics.
Solution 2:
The following is the simpler one. You can define an abstract class which extends the class you want to extend and implement it:
public abstract class TargetClassType extends BasicObject implements CodeObject {
}
now if you want to pass the Class itself, do
public void myMethod(Class<TargetClassType> clazz)
or if you want to pass the class object, write
public void myMethod(TargetClassType clazz)
Either of the above solutions fits your question, but the second one is simpler.
Upvotes: 10
Reputation: 52468
Here is an approach which is a bit verbose, but avoids generics headaches. Create another class which does the extending/implementing:
public abstract class BasicCodeObject
extends BasicObject
implements CodeObject {...}
Then your method can be:
public <T extends BasicCodeObject> void myMethod(Class<T> clazz) {...}
Upvotes: 11
Reputation: 2491
If not all BasicObjects implement CodeObject, then you can use an instanceof / Class.isInstance() check in your method (see http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html):
myMethod(Class<? extends BasicObject> clazz)
{
if (!clazz.isInstance(CodeObject))
{
(indicate that the call was incorrect)
}
...
}
Upvotes: 2