Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Can list hold classes implementing more interfaces

Tags:

java

generics

I am writing NetworkExecutor in Java. I need my Runnable class to implement Serializable too, to be able to send it through the network. I wanted to make my own interface NetworkRunnable like this:

public interface NetworkRunnable extends Runnable, Serializable{}

but then all classes are required to implement NetworkRunnable, although this interface is empty and just unifies Runnable and Serializable interface. I would like to allow classes implementing Runnable and Serializable to be used too. I found it is a possibility to write generic function:

public <T extends Runnable & Serializable> void execute(T command)

This allows using classes implementing just Runnable and Serializable, but I was not able to write List holding these objects. I tried something like:

List<? extends Runnable & Serializable> list=new LinkedList<>();
List<Runnable & Serializable> list=new LinkedList<>();

but it doesn't work. As a solution I can write just List<Runnable> and use it because function <T extends Runnable & Serializable> void execute(T command) will accept just Runnable implementing Serializable too, but it looks like an ugly solution for me.

Is there a way to write List of classes implementing multiple interfaces at once? Or can I somehow specify, that all classes implementing Runnable and Seriablizable implement NetworkRunnable interface too?

EDIT:

I am sorry, I probably didn't specify my problem well. I want to do something like:

public class NetworkThreadPool{
    private List<Runnable & Serializable> waiting=new LinkedList<>();

    @Override
    public <T extends Runnable & Serializable> void execute(T command) {
        waiting.add(command);
    }
}

But I don't know how to declare List of both Runnable and Serializable.

like image 444
google2 Avatar asked Jan 29 '18 13:01

google2


People also ask

Can Java classes implement multiple interfaces?

Java does not support "multiple inheritance" (a class can only inherit from one superclass). However, it can be achieved with interfaces, because the class can implement multiple interfaces. Note: To implement multiple interfaces, separate them with a comma (see example below).

Can a class implements more interfaces?

Your class can implement more than one interface, so the implements keyword is followed by a comma-separated list of the interfaces implemented by the class. By convention, the implements clause follows the extends clause, if there is one.

Can a class implement more than two interfaces?

A class can implement more than one interface at a time.

How many interfaces can a class implement Java?

A class can implement as many interfaces as it desires. In this way, interfaces in Java replace the need for C++'s multiple inheritance (and all of its messy side effects). The previous example defines an interface called Driveable with four methods.


2 Answers

Java doesn't allow you to declare a generic variable with more than one type, only classes and methods may use multiple bounds with the <T extends Foo & Bar> syntax. This is usually not a problem, as in regular code you can usually get by with singular typing (List<Runnable>), using the actual type (List<MyRunnableAndSerializable) or in some cases creating a more specific interface (List<IRunnableAndSerializable).

List<NetworkRunnable> list1;
List<OtherSimilarClass> list2;

public <T extends Runnable & Serializable> void execute(List<T> list) {
    ...
}

The method accepts both and obviously the lists are typed just fine.


However your problem comes from the fact that you have a non-generic class with a generic method, so you don't have a type T for the List.

In this case if Runnable & Serializable is what you need, then you could safely type it as List<Runnable> since Serializable is just a marker interface and execute() makes sure the contents are also Serializable. If the second interface had methods you needed to call, this would of course fail (in this case see the wrapper based answer by @daniu).


In a general situation the Java syntax doesn't allow you to handle this in a straightforward way. You can use a wrapper, but if you want to avoid creating a class just for that you might as well make it a raw list, access it through typed methods to keep it typesafe to outside users and internally use casts and @SuppressWarnings("unchecked") to ignore warnings and show you know what you're doing. That's how it's usually done inside the JDK when Java's generics fail to achieve what is needed.

like image 70
Kayaman Avatar answered Oct 16 '22 09:10

Kayaman


Well since you only have one method everything goes through, you can simply create a Wrapper class and wrap/unwrap on demand.

class NetworkRunnable<T extends Runnable & Serializable> implements Runnable, Serializable {
    private T delegate;
    public NetworkRunnable(T del) {
        delegate = del;
    }
    public T unwrap() {
        return delegate;
    }

    public void run() { delegate.run(); }
}

public class NetworkThreadPool{
    private List<NetworkRunnable> waiting=new LinkedList<>();

    @Override
    public <T extends Runnable & Serializable> void execute(T command) {
        waiting.add(new NetworkRunnable(command));
    }
}
like image 28
daniu Avatar answered Oct 16 '22 10:10

daniu