什么是定义Map <string,?=“”>方法参数</string,>的正确方法

时间:2012-11-14 11:28:44

标签: java generics

我有一个自定义Map to String方法。它适用于任何具有String键的Map,不限于某些特定的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)。

3 个答案:

答案 0 :(得分:5)

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

第一个不起作用,因为你无法调用

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

您怀疑的条目变量的正确类型为Entry<String, ?>

答案 1 :(得分: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的引用应该参数化。但你懒得考虑女巫参数。我看过很多次,人们输入类似:String map2String(Map<?,?> map){...}来删除警告。但它的方法不好。

答案 2 :(得分:0)

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

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

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

public interface AnimalInterface {
    public void makeSound();
}

然后该集合将变为Map<String, AnimalInterface>Map<String, ? extends AnimalBaseClass>。这样,第一个map将接受任何实现AnimalInterface的类,第二个map将接受抽象基类AnimalBaseClass的任何子类,如Dog extends AnimalBaseClass

关于定义列表中关于wildtypes的问题,答案在于java泛型的继承原则,即:List<Integer>不是List<Number>的子类型,而是List<Integer>或{{1 }是List<? extends Integer>的子类型。因此,如果您有List<? extends Number>List<Integer> li,则无法将List<Number> ln等同。但是,如果您将ln = li声明为ln,则等式将有效。但是不要忘记虽然方程式是有效的,但是在列表中添加Numbers会导致编译时错误,例如在List<? extends Number> ln中,因此您的引用将更像是“只读”内容版本。

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

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”。