Java 类型安全:从 Object 到 ArrayList<MyVariable> 的未经检查的强制转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20275623/
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
Type safety: Unchecked cast from Object to ArrayList<MyVariable>
提问by luisgomezcaballero
Here is a part of a program that sends an ArrayList from a server to a client. I want to remove the warning about the last line in this code:
这是将 ArrayList 从服务器发送到客户端的程序的一部分。我想删除有关此代码中最后一行的警告:
Client code:
客户端代码:
Socket s;
(...)
// A server is sending a list from the other side of the link.
ois = new ObjectInputStream(s.getInputStream());
MyList = (ArrayList<MyVariable>) ois.readObject();
MyVariable is a Java class with some attributes. The server is creating an ArrayList and filling it with MyVariable variables as items. Then it sends the complete list to the client.
MyVariable 是一个具有一些属性的 Java 类。服务器正在创建一个 ArrayList 并用 MyVariable 变量作为项目填充它。然后它将完整列表发送给客户端。
I would like to know why do I have a warning there and how to code perfectly in order to have 0 warnings. If it is possible I would like to avoid using "@SuppressWarnings("unchecked")". ;)
我想知道为什么我在那里有警告以及如何完美编码以获得 0 警告。如果可能的话,我想避免使用“@SuppressWarnings("unchecked")”。;)
Thank you,
谢谢,
Luis
路易斯
回答by JB Nizet
It's impossible to avoid this warning. readObject()
returns an Object. You need to cast it. And casting to a generic type will always generate such a warning.
无法避免此警告。readObject()
返回一个对象。你需要投射它。并且转换为泛型类型总是会产生这样的警告。
If you want to make your code as clean as possible, which is a good idea, you should respect the Java naming conventions though, and make variable names start with a lowercase letter.
如果你想让你的代码尽可能干净,这是一个好主意,你应该尊重 Java 命名约定,并让变量名以小写字母开头。
回答by Elliott Frisch
Try this
尝试这个
Object obj = ois.readObject();
// Check it's an ArrayList
if (obj instanceof ArrayList<?>) {
// Get the List.
ArrayList<?> al = (ArrayList<?>) obj;
if (al.size() > 0) {
// Iterate.
for (int i = 0; i < al.size(); i++) {
// Still not enough for a type.
Object o = al.get(i);
if (o instanceof MyVariable) {
// Here we go!
MyVariable v = (MyVariable) o;
// use v.
}
}
}
}
回答by wonder.mice
I don't like that, but you can have a container (sort of an alias or typedef):
我不喜欢那样,但是您可以拥有一个容器(某种别名或 typedef):
// add "implements Serializable" in your case
private static class MyVariableList {
public List<MyVariable> value;
}
And work with MyVariableList
instead. That way you explicitly provide enough information to the compiler to do type checking in runtime.
并与之合作MyVariableList
。这样你就明确地向编译器提供了足够的信息来在运行时进行类型检查。
回答by abhishek
I was running into a similar problem as OP and found a good solution with a combination of comment from @VGR and Java 1.8 method for Arrays.
我遇到了与 OP 类似的问题,并找到了一个很好的解决方案,结合了@VGR 和 Java 1.8 数组方法的注释。
I will provide my answer in terms of OP's question, so it is generic and hopefully helps others:
我将根据 OP 的问题提供我的答案,因此它是通用的,希望对其他人有所帮助:
Instead of returning a collection (list), return an array from the server. Covert collection to an array using the following on the server side code:
myVariableList.toArray(new MyVariable[0]);
If performance is an issue with above, following could be used, so that array does not need to be resized:
myVariableList.toArray(myVariableList.size());
On client side convert array of object, to an array of MyVariable class.
This is specific to JAVA 8.
MyVariable[] myVarArr = Arrays.stream(ois.readObject()).toArray(MyVariable[]::new);
Then, finally convert Array to a Collection (list).
List<MyVariable> myList = Arrays.asList(myVarArr);
不是返回一个集合(列表),而是从服务器返回一个数组。使用以下服务器端代码将集合转换为数组:
myVariableList.toArray(new MyVariable[0]);
如果性能是上述问题,则可以使用以下方法,以便不需要调整数组大小:
myVariableList.toArray(myVariableList.size());
在客户端将对象数组转换为 MyVariable 类数组。
这是 JAVA 8 特有的。
MyVariable[] myVarArr = Arrays.stream(ois.readObject()).toArray(MyVariable[]::new);
然后,最后将 Array 转换为 Collection(列表)。
List<MyVariable> myList = Arrays.asList(myVarArr);
Thanks.
谢谢。
回答by javaGeek
I also ran into a similar situation and was able to solve it. My solution, applied to the example of the OP is this:
我也遇到了类似的情况并且能够解决它。我的解决方案,适用于 OP 的例子是这样的:
myList = (ArrayList<Someclass>) Arrays.asList( (Someclass[]) ois.readObject() );
I have changed the naming-conventions (like suggested by someone, already) to standard Java (objects start with lowercase-characters) and I have renamed the Class MyVariable
to Someclass
to make it explicit, that this really applies to any class (and not just Variables). I'm also assuming, that the corresponding object to myList
on the server-side of type ArrayList<Someclass>
has been written to the stream as an Array Someclass[]
. Note, that this is easily done and analogous to the first part of what abhishek already suggested, but my solution differs on the last step insofar as:
我已经改变了命名的约定标准的Java(如由一个人,已经建议)(对象以小写字符),我已经改名为类MyVariable
,以Someclass
使之明确,这真的适用于任何类(而不仅仅是变量)。我还假设,myList
服务器端类型的相应对象ArrayList<Someclass>
已作为 Array 写入流Someclass[]
。请注意,这很容易完成,类似于 abhishek 已经建议的第一部分,但我的解决方案在最后一步有所不同,因为:
- I'm avoiding to call
Arrays.stream
- It's easier to read and quickly perceived as a simple (without further logic) and
checked
(not generating a warning) cast.
- 我避免打电话
Arrays.stream
- 它更容易阅读并被快速感知为一个简单的(没有进一步的逻辑)和
checked
(不生成警告)强制转换。