哈希表问题

6

我有一个有趣的问题,涉及到使用哈希表;我正在为符合1.4级别的S40诺基亚开发。

我希望哈希表能够按照预期工作:

Hashtable table = new Hashtable();
table.put(1, "Hello World");

不过我遇到了错误:

在类型Hashtable中,方法put(Object, Object)不适用于参数(int, String)

然而当我创建一个对象引用并传递引用时,它就正常工作了!为什么?!

有效示例:

Hashtable table = new Hashtable();
Integer test = new Integer(1);
table.put(test, "Hello World");

任何解释都非常好!

3
你的代码在我的端上运行良好。你确定没有其他潜在问题吗?你确定你的Hashtable是import java.util.Hashtable类型吗? - Arno_Geismar
1
@dan983 - 你确定你在这里发布的是导致错误的实际代码吗?我相信你实际上拥有的是 table.put(1, "Hello World");,这才是真正导致你描述的错误的原因。我在1.4下检查过它,它的表现与你所提供的代码不同。 - Honza Zidek
我正在将Android软件迁移到诺基亚,但似乎诺基亚的功能有些受限。HashTable正在使用@Arno_Geismar导入。 - dan983
我确实使用混淆器(仅在打包jad/jar文件时)。我尝试了强制转换,但是出现了相同的错误。@Honza Zidek,这段代码确实会导致错误,我甚至无法声明泛型类型,因为它强制我使用兼容性1.5! - dan983
【已解决】好的,将编译器兼容级别更改为1.5,然后再更改回1.4似乎修复了问题!我最初使用table.put(1,“Hello World”)进行编译,然后将代码更改为我在此处发布的内容并清理了我的项目,但它可能会混淆。感谢所有人的回复!我会给@HonzaZidek点赞,但您从未留下完整的答案! - dan983
显示剩余7条评论
6个回答

4
在我的回答中,我假设您的实际代码实际上是以下内容:
Hashtable table = new Hashtable();
table.put(1, "Hello World");

这就是导致你所描述错误的代码,即:

Hashtable 类型中的方法 put(Object, Object) 不适用于参数 (int, String)

原因如下:

  1. Java 1.4 不支持泛型,因此 Hashtable 只使用 Objects(作为键和值)。

  2. Java 1.4 不支持自动装箱,因此代码 table.put(1, "Hello World") 不会自动转换为 table.put(Integer.valueOf(1), "Hello World")。因此,您尝试调用不兼容的table.put(int, String)Hashtable.put(Object, Object)

完成。

如果您使用 Java 1.5+,则调用将被自动装箱为 table.put(Integer, String)

另外,不要使用 new Integer(1),总是更喜欢静态工厂方法 Integer.valueOf(1)。您可以避免创建冗余类。 这就是自动装箱编译成的内容。请参阅: 静态工厂方法 vs 实例(普通)构造函数?


我将兼容级别更改为1.5,然后又改回了1.4,现在似乎使用.put(new Integer(1),"Hello World")编译正常了。很酷,感谢您的建议! - dan983
对于Java ME,我需要使用Integer.valueOf("1")。 - dan983
Integer.valueOf(String) 不是 new Integer(int) 的好替代品。从 String 转换甚至更加昂贵。如果你没有 Integer.valueOf(int) 方法,只需使用 new Integer(int) - Honza Zidek

3

根据您提到的错误信息,

类型为Hashtable的put(Object, Object)方法不适用于参数(int, String)

很明显,编译器在Integer对象初始化后立即将其视为原始值。也就是说,它立即应用拆箱。如果我能找到关于这个问题在移动平台上进行优化的参考资料,我会更新我的答案。


我认为Java 1.4中没有可用的自动装箱功能,它是在1.5中引入的。 - naveejr
2
我不相信 OP 在这里放置的代码是导致错误的实际代码。我相信他那里的代码是 table.put(1, "Hello World");,或者类似的东西。 - Honza Zidek
@HonzaZidek 可能是这种情况。我搜索了 J2ME 的拆箱优化,但没有找到令人满意的结果。 - Juvanis
让我们等待原帖作者的回答。我觉得整个问题只是一个错误。 - Honza Zidek

2

您的代码问题在于,正如您所提到的,它是1.4兼容的,这让我想到您正在编译它以使其与1.4兼容。装箱/拆箱是在1.5中添加的功能。

只是为了让您确认我的意思:尝试使用javac --source 1.5 --target 1.5编译您的代码,它将编译成功,但是尝试使用javac --source 1.4 --target 1.4编译相同的代码,那么它将会报错。


0

我不知道在诺基亚手机上开发Java时使用的JVM是哪个(我会假设是Java ME),但在典型的Java SE环境中,您的代码不应该出现错误,而是警告:您没有使用模板来构造HashTable,因此JVM必须假定您的Integer和String是Object类,而不是实际值。

为了避免这个警告,对于某些原因,您的IDE将其报告为错误,请使用:

Hashtable<Integer, String> table = new Hashtable<Integer, String>();
table.put(new Integer(1),"Hello World");

我不认为这是问题。如果他的编译器由于“泛型”而抛出错误,则第二种情况也不应该生效。 - TheLostMind
哪个第二种情况?编译器告诉我们默认的模板实现<Object,Object>不适用于<Integer,String>。然而,这是标准所接受的,但必须先将Integer和String转换为Object,才能调用Hashtable构造函数。 - Alex
为什么编译器会说默认的模板实现<Object, Object>不适用于<Integer, String>? 第二个情况是代码有效的情况。 - TheLostMind
1
这就是为什么我怀疑他没有使用典型的JVM。可能他正在使用Java ME或特定的IDE,在构建之前显示上述消息,即使这不是错误,并且自动转换为父对象是绝对允许的。 - Alex

0

如先前所述,由于您正在运行兼容级别为1.4的Java 1.5版本,因此可能没有自动装箱功能。

我的建议是将您的IDEA JDK设置为1.4,而不是当前使用的1.7版本。


-1

Integer 是一个对象。 int 不是一个对象,它是一个原始类型。 对象 Integer 包装了原始类型 int。 方法 put(Object, Object) 需要两个对象作为参数,而不是一个原始类型和一个对象。


4
new Integer(1) 是一个对象。 - Suresh Atta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接