Java 如何一般地指定可序列化列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/462077/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to generically specify a Serializable List
提问by Megamug
I have the following interface:
我有以下界面:
public interface Result<T extends Serializable> extends Serializable{
T getResult();
}
With that interface, I can not define a variable of type
使用该接口,我无法定义类型的变量
Result<List<Integer>>
because List is not serializable.
因为 List 不可序列化。
However, if I change the interface to this:
但是,如果我将界面更改为:
public interface Result<T> extends Serializable{
T getResult();
}
It now becomes impossible to implement, with compile time checking, because there is no guarantee that T is serializable, and the whole point of the class is to store the result so that I can get it back later, possibly after a transfer over the internet.
现在无法通过编译时检查来实现,因为不能保证 T 是可序列化的,并且该类的重点是存储结果,以便我稍后可以取回它,可能是在通过 Internet 传输之后.
My question is this, is there a way to declare a variable so that it is of two types, or is there some other way to do this that I am not seeing? So, maybe something like:
我的问题是,有没有办法声明一个变量,使其有两种类型,或者有没有其他我没有看到的方法来做到这一点?所以,也许是这样的:
(List<Integer> extends Serializable) value = new ArrayList();
I am trying to put as much of the burden of this problem on the implementation, so that future consumers of this interface are unaware of the problem.
我试图把这个问题的负担尽可能多地放在实现上,这样这个接口的未来消费者就不会意识到这个问题。
Thanks for your help!
谢谢你的帮助!
Here is a more detailed example of what I am trying to do: I am calling a server, The result of which I want to store in a result object, but I do not want to have to deal with casting. So, each method that can be called on the server will define the type of the result by using generics. This result object will also store other meta-data about the result, for example maybe there was too much information to return. In many cases I want to use a list, but the List interface is not serializable, although many of the implementations are.
这是我尝试做的更详细的示例:我正在调用服务器,我想将其结果存储在结果对象中,但我不想处理强制转换。因此,可以在服务器上调用的每个方法都将使用泛型定义结果的类型。这个结果对象还将存储关于结果的其他元数据,例如可能有太多信息要返回。在很多情况下我想使用一个列表,但是 List 接口不是可序列化的,尽管很多实现都是。
So, how to I specify that the type used must be Serializable, but still allow for a List(and not a specific implementation of List) to be used?
那么,如何指定使用的类型必须是可序列化的,但仍然允许使用 List(而不是 List 的特定实现)?
采纳答案by Patrick
You need to declare your variable type as Result<? extends List<Integer>>
.
您需要将变量类型声明为Result<? extends List<Integer>>
.
The type checking knows that List
isn't serializable
, but a subtype of List
can be serializable
.
类型检查知道这List
不是serializable
,但 的子类型List
可以是serializable
。
Here is some sample code. The interface implementation was just done with anonymous inner classes. You can see that the getResult
will return a List<Integer>
on the 2nd object
这是一些示例代码。接口实现只是用匿名内部类完成的。您可以看到getResult
将List<Integer>
在第二个对象上返回 a
Result<Integer> res = new Result<Integer>() {
Integer myInteger;
private static final long serialVersionUID = 1L;
@Override
public Integer getResult() {
return myInteger;
}
@Override
public void addResult(Integer input) {
this.myInteger = input;
}
};
Integer check = res.getResult();
Result<? extends List<Integer>> res2 = new Result<ArrayList<Integer>>() {
ArrayList<Integer> myList;
private static final long serialVersionUID = 1L;
@Override
public ArrayList<Integer> getResult() {
return myList;
}
@Override
public void addResult(ArrayList<Integer> input) {
this.myList = input;
}
};
List<Integer> check2 = res2.getResult();
Edit: Made the example more complete by implementing a void addResult(T input)
interface method
编辑:通过实现void addResult(T input)
接口方法使示例更加完整
回答by Matthew Brubaker
Initial thought. If you are planning on using serialization for any kind of long term data storage, don't. Serialization is not guaranteed to work between invocations of the JVM.
最初的想法。如果您计划将序列化用于任何类型的长期数据存储,请不要这样做。不能保证序列化在 JVM 调用之间工作。
You probably should not be extending Serializable unless you are adding functionality related to Object serialization. Instead, your class that implements Result should also implement Serializable.
除非您要添加与对象序列化相关的功能,否则您可能不应该扩展 Serializable。相反,实现 Result 的类也应该实现 Serializable。
回答by Fabian Steeg
If your intention is to use the Result type for lists in general, and what you want is to make sure the elements of the list are serializable, you could define it like this:
如果您打算将 Result 类型用于一般的列表,并且您想要确保列表的元素是可序列化的,您可以像这样定义它:
public interface Result<T extends List<? extends Serializable>> {}
That way, you could define something like:
这样,您可以定义如下内容:
Result<List<Integer>> r;
But something like this would not compile:
但是这样的事情不会编译:
Result<List<List>> r;
Now if you want to use the result both for, say, Integer, and for List, then the type is not required to be serializable, right? In that case I don't really understand what your goal is.
现在,如果您想将结果同时用于 Integer 和 List,那么该类型不需要可序列化,对吗?在那种情况下,我真的不明白你的目标是什么。
回答by Michael Myers
You could simply declare the variable as Result<ArrayList<Integer>>
. As long as you still program to the List
interface, you haven't really sacrificed replaceability.
您可以简单地将变量声明为Result<ArrayList<Integer>>
. 只要您仍然按照List
接口编程,您就没有真正牺牲可替换性。
I was going to also suggest creating a new interface ListResult
:
我还打算建议创建一个新界面ListResult
:
public interface ListResult<T extends Serializable & List<E extends Serializable>>
implements Result<T> {
T getResult();
}
but then you would still have to declare the variable as ListResult<ArrayList<Integer>>
. So I'd go the simpler route.
但是你仍然需要将变量声明为ListResult<ArrayList<Integer>>
. 所以我会走更简单的路线。
回答by Tom Hawtin - tackline
You kind of can, I think:
你可以,我认为:
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);
}
}
Does that look ugly enought for you?
对你来说,这看起来够丑吗?
Can I suggest that you do not attempt to enforce implementing Serializable
using the Java static type system? It's only an interface because annotations weren't about back then. It's just not practical to enforce it. OTOH, you could enforce it using a type checker that does static analysis in a closed system.
我可以建议您不要尝试Serializable
使用 Java 静态类型系统强制实现吗?它只是一个接口,因为当时还没有注释。执行它是不切实际的。OTOH,您可以使用在封闭系统中进行静态分析的类型检查器来强制执行它。
回答by Megamug
The way I ended up solving this problem is to use this as the interface:
我最终解决这个问题的方法是使用它作为接口:
public interface Result<T> extends Serializable{
T getResult();
}
Then create an implementation for each of the different types of collections as well as one for any object.
然后为每种不同类型的集合创建一个实现,并为任何对象创建一个实现。
So, for example here is what the ListResult class would look like:
因此,例如这里是 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
}
}
回答by Powerlord
Although the List interface doesn't implement Serializable, all of the built-in Collection implementations do. This is discussed in the Collections Implementations tutorial.
尽管 List 接口没有实现 Serializable,但所有内置的 Collection 实现都实现了。这在集合实现教程中进行了讨论。
The Collections Design FAQ has a question "Why doesn't Collection extend Cloneable and Serializable?"which talks about why Sun designed it without extending Serializable.
集合设计常见问题解答有一个问题“为什么集合不扩展 Cloneable 和 Serializable?” 其中讨论了为什么 Sun 设计它而不扩展 Serializable。