0

我的 Java 应用程序显示一些奇怪的行为,我无法找到解决方案。

此代码片段获取LinkedHashMap键和值均为类型的 a 的内容,String并将它们写入文本文件。configWriter是类型PrintWriter

for (Map.Entry<String, String> entry : configMap.entireSet()) {

    configWriter.println(entry.getKey() + "=" + entry.getValue());
}

地图被宣布为:

LinkedHashMap<String, String> configMap = new LinkedHashMap<String, String>();

它是通过使用Scanner该类从文本文件中读取标记来填充的。

映射中的一个值是 aString只包含数字(一个整数),但是当循环到达这个值时,它会抛出一个ClassCastException说法,即不能从Integerto 转换String。这很有意义,但值的类型是字符串。

有没有办法强制 Java 将此值保留为String?

4

2 回答 2

7

几乎可以肯定的是 rawtypes 正在某个地方被使用,并且有一种Integer潜入地图的方式。

识别an插入地图的最简单方法是将初始化替换IntegerconfigMap

Map<String, String> configMap = Collections.checkedMap(
  new LinkedHashMap<String, String>(), String.class, String.class);

String如果将 a 以外的内容插入到地图中,这实际上会引发异常。我个人不会在生产代码中使用它,但这可能是“消除”错误的最简单方法;你会得到一个异常和一个堆栈跟踪,以确定Integer插入的确切位置。

就目前而言,使用类型擦除实现泛型的方式意味着实际上没有什么可以阻止将非String值插入到映射中。编译器会做出一些努力来阻止它,但原始类型和遗留代码可以绕过它。但是,使用Collections.checkedMap会强制解决这个问题。

于 2012-06-14T02:30:52.820 回答
2

Louis Wasserman 已经解释了您的问题的可能原因。

我只想指出,您对问题的思考存在一些缺陷。

为什么Java在读取LinkedHashMap时会自动从String转换为Integer

首先,您不能从 aString转换为Integer。使用 Java 引用类型,您只能将对象转换为该类型的实例或该类型的子类型。该String类型不是 的子类型Integer,因此 JVM 的操作语义禁止这样的转换 - 如果您编写了尝试执行此操作的可编译代码,您将获得运行时异常。

其次,在LinkedHashMap... 或任何其他集合类中没有任何内容可以元素/键/值实例从转换String为 ,Integer而无需您告诉它。行为良好的 (Java) API 不会做那种事情。

这让我们回到了路易斯的诊断——某些东西(例如你的代码)已经将该Integer对象添加为一个值。如果您使用原始类型或抑制/忽略“未经检查的转换”警告,就会发生这种情况。

于 2012-06-14T02:49:08.823 回答