Java:可以列出实现更多接口的保持类

时间:2018-01-29 13:20:08

标签: java generics

我在Java中编写NetworkExecutor。我需要我的Runnable课程来实现Serializable,以便能够通过网络发送它。我想像这样建立我自己的界面NetworkRunnable:

public interface NetworkRunnable extends Runnable, Serializable{}

但是所有类都需要实现NetworkRunnable,尽管此接口为空并且只是统一RunnableSerializable接口。我想允许使用实现RunnableSerializable的类。我发现编写泛型函数是可能的:

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

这允许使用仅实现RunnableSerializable的类,但我无法编写保存这些对象的List。我试过像:

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

但它不起作用。作为一种解决方案,我只能编写List<Runnable>并使用它,因为函数<T extends Runnable & Serializable> void execute(T command)也只接受Runnable实现Serializable,但对我来说它看起来像一个丑陋的解决方案。

有没有办法一次编写实现多个接口的类列表?或者我可以以某种方式指定实现RunnableSeriablizable的所有类都实现NetworkRunnable接口吗?

编辑:

对不起,我可能没有详细说明我的问题。我想做点什么:

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

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

但我不知道如何声明ListRunnable的{​​{1}}。

2 个答案:

答案 0 :(得分:10)

Java不允许您声明具有多种类型的泛型变量,只有类和方法可以使用<T extends Foo & Bar>语法的多个边界。这通常通常不是问题,因为常规代码通常可以通过单一输入(List<Runnable>),使用实际类型(List<MyRunnableAndSerializable)或在某些情况下创建更具体的界面(List<IRunnableAndSerializable)。

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

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

该方法接受两者,显然列表输入正常。

但是,您的问题来自于您使用泛型方法的非泛型类,因此您没有类型{{1对于T

在这种情况下如果您需要List,那么您可以安全地输入Runnable & Serializable,因为List<Runnable>只是一个标记界面而Serializable 1}}确保内容也是execute()。如果第二个接口有你需要调用的方法,那么这当然会失败(在这种情况下,请参阅@daniu的基于包装器的回答)。

在一般情况下,Java语法不允许您以直接的方式处理此问题。您可以使用包装器,但如果您想避免为此创建类,您也可以将其作为原始列表,通过类型化方法访问它以使其对外部用户的类型安全并在内部使用演员和Serializable忽略警告,并告诉你你知道自己在做什么。这就是当Java的泛型无法实现所需要的时候,它通常在JDK内部完成的方式。

答案 1 :(得分:3)

好吧,因为你只有一个方法,所以你可以简单地创建一个Wrapper类并根据需要打包/解包。

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