简体   繁体   中英

Method argument extends class implements interface

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

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM