`

那一年你定义了一个接口

    博客分类:
  • java
阅读更多
那一年,你定义了一个接口:

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;  
//    }  

    public void addExtInfo(String key, String value) {  
        if (extInfoList == null) {
			extInfoList = new ArrayList<MatchVariable>();
		}
		extInfo.add(new MatchVariable(key, value));
    }  
      
}  


猪队友猫队友再也传不了其他类型的参数给你了。


0
0
分享到:
评论
1 楼 飞天奔月 2016-05-28  
写得有趣 ^_^

相关推荐

    java面试宝典

    72、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73、线程的基本概念、线程的基本状态以及状态之间的关系 18 74、sleep() 和 wait() 有什么区别? 18 75、socket通信...

    什么是VLAN

    但是路由器的物理端口只应该可以分配一个IP地址,那怎样来区分不同网段了?这就可以在这个物理端口下,创建两个子接口---逻辑接口实现。  比如逻辑接口F0/0.1就分配IP地址192.168.1.1/25,用于销售部,而F0/0.2就...

    VC++6.0核心编程源码.rar

    比如说,你编写了一个你希望其他人调用的函数。你的函数可能因为这样或那样的原因而运行失败,你必须向函数的调用者说明它已经运行失败。 若要指明函数运行失败,你只需要设定线程的最后的错误代码,然后让你的函数...

    c#学习笔记.txt

    一个接口定义一个协定。实现接口的类或结构必须遵守其协定。接口可以从多个基接口继承,而类或结构可以实现多个接口。接口可以包含方法、属性、事件和索引器。接口本身不提供它所定义的成员的实现。接口只指定实现该...

    大智慧股票本地数据读取接口(含源码)

    2)如果数据文件已经被分析家等软件占用导致无法打开时,将自动复制一份该文件,并从该备份文件中读取数据. 3)程序将自动补充数据,即如果目标表不存在,则建立并添加数据,如果目标表已存在,则判断表中每只证券的最新 ...

    JAVA上百实例源码以及开源项目

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    jsr80 java 访问 usb

    每一个配置都有一个或者多个 接口,它可以视为一个物理通信渠道 ;每一个接口有零个或者多个端点,它可以是数据提供者或者数据消费者,或者同时具有这两种身份。接口由接口描述符描述,端点由端点描述符描述。并且一...

    硬盘工作原理

    1956年IBM的一个工程小组向世界展示第一台磁盘存贮系统Ramac,1968年Winchester技术被提出,硬盘走过了50年的历程,虽然硬盘技术上有很多的进步,衍生出了SCSI、IDE、SATA等多种不同的形式,那只是为了适应新的应用...

    jpivot学习总结.doc

    formatter 该属性定义了 Member.getCaption() 方法返回的动作值,这里需要是一个实现了 mondrian.olap.MemberFormatter 接口的类,用来对 Caption 地值进行格式化。 3.6. Join 对于一个 Hierarchy 来说,有两种...

    千方百计笔试题大全

    72、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73、线程的基本概念、线程的基本状态以及状态之间的关系 18 74、sleep() 和 wait() 有什么区别? 18 75、socket...

    JAVA上百实例源码以及开源项目源代码

    5个目标文件,演示Address EJB的实现 ,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    C#微软培训资料

    第三章 编写第一个应用程序 .20 3.1 Welcome 程序 .20 3.2 代 码 分 析 .20 3.3 运 行 程 序 .23 .4 添 加 注 释 .25 3.5 小 结 .27 第二部分 C#程序设计基础.28 第四章 数 据 类 型 .28 4.1 值 类 型...

    MIT科技评论:2020年全球突破性技术Top10

     《麻省理工科技评论》每年遴选并公布10项即将对人们工作生活产生深远影响的重大技术,这十大技术有一个基本的标准,那就是“该项技术已经达到一个里程碑式的阶段或即将到达这一阶段”,所以我们在看到这十大技术的...

    LinuxC编程一站式学习

    本书尽最大努力理清概念之间的依赖关系,力求一站式学习,读者不需要为了找一个概念的定义去翻其它书,也不需要为了搞清楚一个概念在本书中前后一通乱翻,只需从前到后按顺序学习即可。但一站式学习并不等于傻瓜式...

    我是如何通过反射机制写一个通用excel导入导出的【上篇–导入】

    快一年没写推文了,感觉肚子里也积了点东西,今天就搞一搞个人觉得还是挺酷的东西–结合反射机制搞一个通用Excel...但是当需要读取的Excel越来越多的时候,每来一个模板就写一个Excel,来一个写一个的话,那就很难受了

    xml入门教程/xml入门教程

    --只能有一个根元素即那一对根标签--&gt; &lt;root&gt;&lt;!--根标签--&gt; &lt;!--根元素的内容--&gt; &lt;leaf&gt;&lt;!--子元素--&gt; ... XML文件的写法 xml文档是有标签和标签中的内容组成的,标签和标签中的内容合成为元素 非空元素 (起始...

    (完整word版)python3基础教程.doc

    Python由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年. 像Perl语言一样, Python 源代码同样遵循 GPL(GNU General Public License)协议. 现在开始学习 Python! 谁适合阅读本教程? 本教程适合想...

    一个进程池的服务器程序

    一个进程池的服务器程序 下面做了非常简单的http服务器,该服务器只能接收Get请求。 流程大概如下: 1,父进程listen,创建pipe(下面所有父子进程之间的通信都用该pipe) 2,父进程预fork n个子进程 3,各个子...

Global site tag (gtag.js) - Google Analytics