那一年,你定义了一个
接口:
class="java" name="code">public interface WtfService {
public void process(WtfDto dto);
}
为了良好的
扩展性,你定义了一个扩展字段,Map<String, String>类型,并且在文档里强调了“key和value都是String类型”:
public class WtfDto implements Serializable {
//other fields
private Map<String, String> extInfo;
public Map<String, String> getExtInfo() {
return extInfo;
}
public void setExtInfo(Map<String, String> extInfo) {
this.extInfo = extInfo;
}
}
然后实现这个接口:
public class WtfServiceImpl implements WtfService {
public void process(WtfDto dto) {
Map<String, String> extInfo = dto.getExtInfo();
for (Entry<String, String> entry : extInfo.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
}
}
测试
@Test
public void normal() {
WtfService service = new WtfServiceImpl();
WtfDto dto = new WtfDto();
Map<String, String> extInfo = new HashMap<String, String>();
extInfo.put("name", "Kobe");
dto.setExtInfo(extInfo);
service.process(dto);
}
一切正常。世界看起来是那么完美。
直到某一天,你看到这样的一个报错:
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.String
at com.sample.WtfServiceImpl.process(WtfServiceImpl.java:40)
你百思不得期解:
明明是Map<String, String>类型,怎么会有Double?
难道调用方还能传一个Double过来?
自己传一个Double看看:
@Test
public void error() {
WtfService service = new WtfServiceImpl();
WtfDto dto = new WtfDto();
Map<String, Object> extInfo = new HashMap<String, Object>();
extInfo.put("name", 10.999);
dto.setExtInfo(extInfo); //编译不通过
service.process(dto);
}
编译不通过。
那Double到底是怎么传过来的?
真相是:
@Test
public void warning() {
WtfService service = new WtfServiceImpl();
WtfDto dto = new WtfDto();
//Map<String, Object> extInfo = new HashMap<String, Object>();
Map extInfo = new HashMap(); //eclipse在这一行会有warning提示
extInfo.put("name", 10.99);
dto.setExtInfo(extInfo);
service.process(dto);
}
}
对于没有代码洁癖直接忽视waring或者压根就不懂得
泛型的猪队友,他就那么自然而然的写出了上面的代码。
虽然有warning,但毕竟编译通过了。
于是你的服务就理所当然的报错了。
你体会到这个世界的残酷了。
你应该像王叔叔那样,定义一个key-value的类:
public class MatchVariable implements Serializable {
private String key;
private String value;
//getter/setter
}
然后把接口的参数类改成这样:
public class WtfDto implements Serializable {
//...other fields
// private Map<String, String> extInfo;
//
// public Map<String, String> getExtInfo() {
// return extInfo;
// }
//
// public void setExtInfo(Map<String, String> extInfo) {
// this.extInfo = extInfo;
// }
private List<MatchVariable> extInfoList;
public List<MatchVariable> getExtInfoList() {
return extInfoList;
}
//根据Effective java这本书的建议,你不应该直接提供setExtInfoList这样的方法
public void setExtInfoList(List<MatchVariable> extInfoList) {
this.extInfoList = extInfoList;
}
}
猪队友猫队友再也传不了其他类型的参数给你了。