3

我有一个自定义 Map to String 方法。它适用于任何类型的具有 String 键的 Map,不限于某些特定的映射值类型。例如,映射值可能来自javax.jms.Message.getObjectProperty(String name)方法,或者只是纯字符串。

以下哪个是最“正确”的方法签名,为什么,或者都是平等的?

String map2String(Map<String, Object> map){...}

或者

String map2String(Map<String, ?> map){...}

或者

String map2String(Map<String, ? extends Object> map){...}

或(添加编辑)

<E> String map2String(Map<String, ? extends E> map){...}

或者是其他东西?

此外,该方法包含类似于这样的 for-each 循环:

for(Entry<String, ?> entry : map.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue().toString();
}

哪个是entry变量的“正确”类型,是否重要(?映射中的不兼容组合除外,Object在条目类型中)。

4

3 回答 3

5

String map2String(Map<String, ?> map){...}是正确的(? extends Object是多余的)

第一个不起作用,因为你不能打电话

Map<String,Integer> myMap = {...}
map2String(myMap); // Map<String,Integer>  is not  Map<String,Object>  

条目变量的正确类型Entry<String, ?>正如您所怀疑的那样。

于 2012-11-14T11:49:37.623 回答
1

最好的方法是使用您发布的第一个示例,而不是Object使用您的类类型。否则,您必须将 Object 转换为其他类或使用instanceof,这不是一个好主意

 String map2String(Map<String, YourClass> map){...}

关于其他:

String map2String(Map<String, ? extends Object> map){...}

好吧,? extends Object这不是最好的选择,因为每个类都派生自Object. ? extends Object和之间没有区别?

extends在以下情况下可以使用通配符:

class MyClass extends RootClass
....
class YourClass extends RootClass
....
String map2String(Map<String, ? extends RootClass> map)   // this method can fetch argumets by type of Map  `MyClass` and `YourClass`.

更远:

String map2String(Map<String, ?> map){...}

假设您没有使用String map2String(Map map){...}任何类型。编译器会告诉你: Map 是一种原始类型。对泛型类型 Map 的引用应该被参数化。但是您懒得考虑要采用的女巫参数。我看到很多次,人们键入:String map2String(Map<?,?> map){...}删除警告。但它的坏方法。

于 2012-11-14T11:38:38.363 回答
0

处理集合我会选择继承和泛型作为原则。

例如,我会声明一个接口或抽象基类,并将其作为集合类型参数传递,例如:

public abstract class AnimalBaseClass {
    //...
    public abstract void makeSound();
}

public interface AnimalInterface {
    public void makeSound();
}

然后集合将变成Map<String, AnimalInterface>or 或Map<String, ? extends AnimalBaseClass>。这样,第一个映射将接受任何实现AnimalInterface的类,第二个映射将接受抽象基类的任何子类AnimalBaseClass,例如Dog extends AnimalBaseClass.

至于您关于定义列表中的野生类型的问题,答案在于java泛型的继承原则,即:List<Integer>不是 的子类型List<Number>,而是List<Integer>orList<? extends Integer>的子类型List<? extends Number>。所以,如果你有List<Integer> li并且List<Number> ln你不能等同于ln = li. ln但是,如果您声明List<? extends Number> ln等式将有效。但不要忘记,虽然等式是有效的,但将 Numbers 添加到列表中会导致编译时错误,例如 in ln.add(new Float()),因此您的引用将更像是内容的“只读”版本。

因此,您的通用方法将变为:

public <T extends YourBaseClass> String map2String(Map<String, T> map) {
    //do something with your map and return a String object
}

而且,如果你想Object成为你的基类,只需省略' extends YourBaseClass'。

于 2012-11-14T12:36:45.690 回答