我有一个自定义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
)。
答案 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
”。