Java 如何一般性地指定可序列化列表

Java 如何一般性地指定可序列化列表,java,generics,serialization,Java,Generics,Serialization,我有以下界面: public interface Result<T extends Serializable> extends Serializable{ T getResult(); } public interface Result<T> extends Serializable{ T getResult(); } 公共接口结果扩展可序列化{ T getResult(); } 使用该接口,我无法定义类型为的变量 Result<List<

我有以下界面:

public interface Result<T extends Serializable> extends Serializable{
    T getResult();
}
public interface Result<T> extends Serializable{
    T getResult();
}
公共接口结果扩展可序列化{
T getResult();
}
使用该接口,我无法定义类型为的变量

Result<List<Integer>>
结果
因为列表不可序列化

但是,如果我将界面更改为:

public interface Result<T> extends Serializable{
    T getResult();
}
公共接口结果扩展可序列化{
T getResult();
}
现在不可能通过编译时检查来实现,因为不能保证T是可序列化的,而类的全部目的是存储结果,以便我可以稍后(可能是在通过internet传输之后)将其取回

我的问题是,有没有一种方法可以声明一个变量,使其具有两种类型,或者有没有其他方法可以做到这一点,我没有看到?所以,也许是这样的:

(List<Integer> extends Serializable) value = new ArrayList();
Result<List<Integer>> r;
(List extensed Serializable)value=new ArrayList();
我试图把这个问题的重担尽可能多地放在实现上,这样这个接口的未来消费者就不会意识到这个问题

谢谢你的帮助

下面是一个更详细的示例,说明我正在尝试做什么: 我正在调用一个服务器,我想将其结果存储在一个result对象中,但我不想处理强制转换。因此,可以在服务器上调用的每个方法都将使用泛型定义结果的类型。此结果对象还将存储有关结果的其他元数据,例如,可能返回的信息太多。在许多情况下,我希望使用列表,但是列表接口是不可序列化的,尽管许多实现是可序列化的


那么,如何指定所使用的类型必须是可序列化的,但仍然允许使用列表(而不是列表的特定实现?

最初的想法。如果您计划将序列化用于任何类型的长期数据存储,请不要这样做。序列化不能保证在JVM调用之间工作


除非添加与对象序列化相关的功能,否则可能不应该扩展Serializable。相反,实现Result的类也应该实现Serializable。

如果您的目的是在一般情况下对列表使用Result类型,并且您想要的是确保列表的元素是可序列化的,您可以这样定义它:

public interface Result<T extends List<? extends Serializable>> {}

public interface Result您只需将变量声明为
Result
。只要您仍然编程到
列表
界面,就不会真正牺牲可替换性

我还打算建议创建一个新的界面
ListResult

public interface ListResult<T extends Serializable & List<E extends Serializable>>
        implements Result<T> {
    T getResult();
}
公共接口列表结果
实现结果{
T getResult();
}

但是,您仍然必须将变量声明为
ListResult
。所以我会选择更简单的路线。

我想你可以:

public class Thing<T extends Serializable> implements Serializable {
    private static class Holder<V extends Serializable> {
        private final V value;
        private Holder(V value) {
            this.value = value;
        }
    }
    private Holder<? extends List<T>> holder;
    private <V extends List<T> & Serializable> void set(V value) {
        holder = new Holder<V>(value);
    }
}
public类实现了可序列化{
私有静态类持有者{
私人最终V值;
私人持有人(V值){
这个值=值;
}
}

private Holder我最终解决这个问题的方法是使用它作为接口:

public interface Result<T extends Serializable> extends Serializable{
    T getResult();
}
public interface Result<T> extends Serializable{
    T getResult();
}
公共接口结果扩展可序列化{
T getResult();
}
然后为每种不同类型的集合以及任何对象创建一个实现

例如,下面是ListResult类的外观:

public class ListResult<T> implements Result<List<T>>{
    public List<T> getResult(){
        //return result
    }

    public <V extends List<T> & Serializable> void setResult(V result){
        //store result
    }
}
公共类ListResult实现结果{
公共列表getResult(){
//返回结果
}
公共无效设置结果(V结果){
//存储结果
}
}

您需要将变量类型声明为
结果尽管列表接口没有实现可序列化,但所有内置集合实现都实现了可序列化。这在集合中进行了讨论


“集合设计常见问题解答”有一个问题,它谈到了Sun为什么在不扩展Serializable的情况下设计它。

您能澄清一下您想做什么吗?也许可以给出一个更大的例子吗?您应该知道,即使T标记为Serializable,它仍然可以包含对非serialiazble对象的引用。因此,它将传递Generalics静态分析,但在运行时失败。是的,但这是使用者犯的错误,而不是我代码中的缺陷。如果使用者声明某个东西可序列化,然后又不符合可序列化的要求,我无能为力。我没有将其用于长期数据存储。对不起,当我说“该类的全部目的是存储结果",我的意思是以后在程序的同一个实例中。它需要考虑任何可序列化的对象,而不仅仅是列表。它需要可序列化,以便可以在服务器和客户端之间传输。如果类型需要可序列化,则不能是列表。如果要使用列表,则不能要求它可序列化。我不能hink我看不出你在寻找什么样的解决方案,对不起。它可以是一个列表,并且可以序列化。例如,java.util.ArrayList。我不明白这两件事是如何对立的。我想让我的消费者使用他们选择的列表实现,只要它是可序列化的。有三种方法可以使用它。获取result,设置结果并传输结果。若要传输,您必须知道它是可序列化的。若要获取,您必须知道它是一个列表。若要设置,您必须知道它是一个列表并可序列化。我想让每个人只知道他们需要什么。希望这有帮助!我不想强制服务器指定将返回的实现,因为这样它将I’我不能被动更改。这不是我需要的,因为我不能假设它是一个列表。但是,当我刚做“V extends T&Serializable”时,我得到了一个例外。这可能是另一个问题的主题。太棒了!我开始认为没有办法做到这一点。谢谢!好的,我知道了