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
.
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).
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.
A class can implement more than one interface at a time.
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.
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.
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));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With