繁体   English   中英

使用泛型的 Hashmap 的 getter setter

[英]getter setter for Hashmap using generics

我有以下两个类

动物类

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 中键的数据类型将始终是字符串,但值的数据类型将是随机的,因此我尝试使用泛型。

来自 PHP 背景的我仍然无法掌握 Java 泛型的概念。 你能告诉我代码中的错误在哪里吗?

应该为此使用Map 这不像 PHP。

相反,您应该创建一个知道每个字段类型的类:

class Animal {
  String name;
  String favfood;
  int someIntegerField;
  List<Foo> someListField;
  ...
}

当所有键和所有值都具有相同类型时,您真的应该只使用Map

虽然这种设置不是理想的方法,但一种解决方案是使您的 Map 成为<String, 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);
      }
    }
A cannot be resolved to a type

这只是意味着您正在使用不存在的“A”类。 例如这里Map<String, A> data你说的Map<String, A> data ,你正在创建 Map,其中字符串是键,值是类型“A”。

相比之下,这个Map<String, Integer>意味着你创建了一个映射,它以字符串作为键,整数作为其键的关联值。

您的Map<String, A>在其声明中具有未定义的类型A 问题是, A从未被指定,因此不能用作任何类型的类型。

解决方案是使用通配符类型或使用Object而不是A

下面是两个示例解决方案: Map<String, ?> data = new HashMap <String, ?>(); Map<String, Object> data = new HashMap <String, Object>();

同样的事情必须应用于你的Dog类中的地图。

问题是你不能只在 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;
   }
}

然而,问题是,当你初始化一个新的Animal时,你需要定义A ,例如:

Animal<String> dog = new Animal<>();
dog.setValue("name", "max");  //<---- ok
dog.setValue("age", 13);      //<---- won't compile

然而,这意味着您的data Map 只能从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

到了这个阶段,类型信息已经丢失,你只剩下一个映射StringObject映射

请记住,您不应混合使用 Generic type 和 RAW type same 。 我认为最简单的方法是使用Object而不是A

Map<String, Object> data = new HashMap <String, Object>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM