方法参数扩展类实现接口

我有以下类和接口:

public class BasicObject{...}
public interface CodeObject{...}

我想创建一个方法,其中的参数需要类型为 BasicObject 并实现 CodeObject。我尝试了下面的代码,但是它不能保证 clazz 是一个实现 CodeObject 的类。

myMethod(Class<? extends BasicObject> clazz){...}

我想这样做,但它不能编译:

myMethod(Class<? extends BasicObject implements CodeObject> clazz){...}
115503 次浏览

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)
}
...
}

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)

    These are just wrong syntax according to Java.

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) {...}

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.