我有以下两个类
动物类
class Animal {
Map<String, A> data = new HashMap <String, A>();
public void setValue(HashMap<String, ?> val)
{
this.data = val;
}
public Map getValue()
{
return this.data;
}
}
狗类
class Dog extends Animal {
public void index()
{
Map<String, A> map = new HashMap<String, A>();
map.put("name", "Tommy");
map.put("favfood", "milk"); // want to pass Lists, Integers also
setValue(map);
}
}
从上面的代码中我可以看到,我正在尝试使用index
方法中的键设置一些值,但是我在两个文件中都收到来自eclipse的错误警告。错误消息是:
在狗类文件中:
Multiple markers at this line
- A cannot be resolved
to a type
- A cannot be resolved
to a type
在动物类文件中:
Multiple markers at this line
- A cannot be resolved to a type
- A cannot be resolved to a type
- Incorrect number of arguments for type Map<K,V>; it cannot be parameterized with arguments
<HashMap<String,A>>
HashMap中键的数据类型将始终为String,但值的数据类型将是随机的,因此我尝试使用泛型。
来自PHP背景我仍然无法掌握Java Generics的概念。你能告诉我我的代码中的错误在哪里吗?
答案 0 :(得分:1)
你应该不为此使用Map
;这不像PHP。
相反,您应该创建一个知道每个字段类型的类:
class Animal {
String name;
String favfood;
int someIntegerField;
List<Foo> someListField;
...
}
当所有键和所有值具有相同类型时,您应该只使用Map
。
答案 1 :(得分:1)
虽然这种设置不是理想的方法,但一种解决方案是使您的Map成为<String, Object>
泛型类型。通过这种方式,您可以将任何想要的内容放入Object部分。然而,将这些信息撤回是一种痛苦。这就是我看到你的课程发生变化的方式。
class Animal {
Map<String, Object> data = new HashMap <String, Object>();
public void setValue(Map<String, Object> map)
{
this.data = map;
}
public Map<String, Object> getValue()
{
return this.data;
}
}
class Dog extends Animal {
public void index()
{
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "Tommy");
map.put("favfood", "milk"); // want to pass Lists, Integers also
setValue(map);
}
}
答案 2 :(得分:0)
A cannot be resolved to a type
这只意味着你正在使用课程&#34; A&#34;哪个不存在。例如,你在Map<String, A> data
说,你正在创建Map,其中string是键,值是&#34; A&#34;。
在比较中,这个Map<String, Integer>
意味着你创建了map,它将string作为键,整数作为其键的关联值。
答案 3 :(得分:0)
您的Map<String, A>
在其声明中包含未定义的类型A
。
问题是,A
从未指定,因此不能用作任何类型。
解决方案是使用通配符类型或使用Object
代替A
。
以下是两个示例解决方案:
Map<String, ?> data = new HashMap <String, ?>();
要么
Map<String, Object> data = new HashMap <String, Object>();
同样的事情必须应用于Dog
班级的地图。
答案 4 :(得分:0)
问题是你不能在Java泛型中引入一个类型参数并期望它能够工作。例如,查看Animal
类:
class Animal {
Map<String, A> data = new HashMap <String, A>();
public void setValue(HashMap<String, ?> val)
{
this.data = val;
}
public Map getValue()
{
return this.data;
}
}
未定义类型参数A
,因此在这种情况下,编译器将查找类名A
。您可以通过为类引入类型参数来解决此问题:
class Animal<A> { // <--- <A> introduces A as a type parameter
Map<String, A> data = new HashMap <String, A>();
public void setValue(HashMap<String, ?> val)
{
this.data = val;
}
public Map getValue()
{
return this.data;
}
}
但问题是,您需要在初始化新A
时定义Animal
,例如:
Animal<String> dog = new Animal<>();
dog.setValue("name", "max"); //<---- ok
dog.setValue("age", 13); //<---- won't compile
但是,这意味着您的data
地图只能从String
映射到String
,您将无法存储整数。
你可以通过使用通配符解决这个问题,例如:
class Animal {
Map<String, ?> data = new HashMap <String, A>();
public void setValue(HashMap<String, ?> val)
{
this.data = val;
}
public Map getValue()
{
return this.data;
}
}
现在,您可以在地图中存储从Object
派生的每种数据类型,String
甚至Integer
。
Animal dog = new Animal();
dog.setValue("name", "max"); //<---- ok
dog.setValue("age", 13); //<---- ok
此解决方案的问题在于您只能以类型保存方式检索此地图中的元素。
dog.getValue().get("name") //<---- ok
Object name = dog.getValue().get("name") //<---- ok
- 但是 -
String name = dog.getValue().get("name") //<---- won't compile
在此阶段,类型信息已丢失,您将看到一张将String
映射到Object
的地图
答案 5 :(得分:0)
请记住,您不应混合使用 Generic type 和 RAW type same 。我认为最简单的方法是使用 Object
代替 A
:
Map<String, Object> data = new HashMap <String, Object>();