简体   繁体   中英

How to satisfy parameter type Class<? extends someInterface> in java

Consider the following code

@Test
public void testFunction() {
    // This cause error
    callDoSomething(new myInterfaceImpl());
}

public interface myInterface {
    int doSomething();
}

public class myInterfaceImpl implements myInterface {
    public int doSomething() {
        return 1;
    }
}

public void callDoSomething(Class<? extends myInterface> myVar) {
    System.out.println(myVar.doSomething());
}

On this line callDoSomething(new myInterfaceImpl()); I get the following error.

Error:(32, 25) java: incompatible types: com.myProject.myTest.myInterfaceImpl 
cannot be converted to java.lang.Class<? extends com.myProject.myTest.myInterface>

How do I satisfy the parameter type? If only an interface is provided to me.

I want to bound the class that has an interface, but it seems like this is not avaiable to me

Class<? implements myInterace>

Edit:

The reason I want to do this is because I want to provide a custom kafka partitioner.

    public Builder<K, V> withCustomPartitionner(Class<? extends Partitioner> customPartitioner) {
        this.customPartitioner = customPartitioner;
        return this;
    }

It looks like you want to be able to call methods on the parameter that's given. In that case, you'll want the actual instance of your interface, not the Class associated with it.

public void callDoSomething(myInterface myVar) {
    System.out.println(myVar.doSomething());
}

Class<> is used when you want to use reflection to do something with the specific class type that you're interested in:

public void outputClassInfo(Class<? extends myInterface> myClass) {
    System.out.println(myClass.getName());
}

If that's what you're going for, you'll want to provide the class at compile time like this:

outputClassInfo(myInterfaceImpl.class);

Or, if you won't know which class you're dealing with until runtime, you can use reflection:

myInterface thing = getThing();
outputClassInfo(thing.getClass());

So, in the example you're providing in your edit, I'm guessing you want:

public Builder<K, V> withCustomPartitioner(Class<? extends Partitioner> customPartitioner) {
    this.customPartitioner = customPartitioner;
    return this;
}

// Usage
builder
    .withCustomPartitioner(FooPartitioner.class)
    ...

The parameter to callDoSomething shouldn't be a class. It must be an instance of that class or it's subclass.

public <T extends myInterface> void callDoSomething(T myVar) {
    System.out.println(myVar.doSomething());
}

On a side note, don't name Java classes/interfaces starting with lower case.

As rightly mentioned by Andy Turner@, there is no need to use a type parameter here and you can just refer to the type as myInterface

public void callDoSomething(myInterface myVar) {
    System.out.println(myVar.doSomething());
}

This type Class<? extends myInterface> myVar Class<? extends myInterface> myVar corresponds to a Class instance not to an instance of myInterface .
You generally don't pass a class as parameter (but for reflection purposes or to bypass generics erasures). So what you need as parameter is probably :

public void callDoSomething(myInterface myVar) {
    System.out.println(myVar.doSomething());
}

That you could invoke :

@Test
public void testFunction() {
    // This cause error
    callDoSomething(new myInterfaceImpl());
}

您需要传递Class而不是实例。

callDoSomething(MyInterfaceImpl.class);

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