问题的引入
classify方法被重载了,而要调用那个重载方法是在编译时做出决定的。
虽然for循环中的三次迭代的运行时类型是不同的,但这并不影响对重载方法的选择。
因为该参数的编译时类型为Collection<?>,所以,唯一合适的重载方法是第三个:classify(Collection c)。
重载与重写的区别
对于重载方法的选择是静态的,而对于被覆盖的方法的选择则是动态的。
选择被覆盖的方法的正确版本是在运行时进行的,选择的依据是被调用方法所在对象的运行时类型。
如何修复引入的问题
最佳修正方案是:用单个方法来替换这三个重载的classify方法,并在这个方法中做一个显式的instanceof测试:
覆盖机制是规范,而重载机制是例外,所以覆盖机制满足了人们对于方法调用行为的期望。
如果编写出来的代码的行为可能使程序员感到困惑,它就是很槽糕的实践。
应该避免胡乱地使用重载机制。
建议
安全而保守的策略是,永远不要导出两个具有相同参数数目的重载方法。
如果方法使用可变参数,保守的策略是根本不要重载它。
始终给方法起不同的名称,而不使用重载机制。
对于每一对重载方法,至少有一个对应的参数在两个重载方法中具有“根本不同”的类型。
如果重载方法在同样的参数上被调用时,执行相同的功能,重载就不会带来危害。
确保这种行为的标准做法是,让更具体化的重载方法把调用转发给更一般化的重载方法。
例如String类的:
自动装箱
在JDK5之前,所有的基本类型都根本不同于所有的引用类型,但是自动装箱改变了这种情况。
如何解决这个问题:
总结
避免:同一组参数只需经过类型转换就可以被传递给不同的重载方法。
当传递相同的参数时,所有重载方法的行为必须一致。