7.41 审慎使用方法重载(overloading)
7.41 谨慎使用方法重载(overloading)
以下类对不同的集合类型分类,classify()方法被重载:
public class CollectionClassifier { public static String classify(Set<?> s){ return "Set"; } public static String classify(Collection<?> c){ return "Collection"; } }
以下测试将失败:
@Test public void testCollectionClassifier(){ Collection<String> c=new HashSet<String>(); //因为c声明为Collection类型,而重载方法的选择是在编译时决定的, //所以最终会调用classify(Collection<?> c) Assert.assertEquals(CollectionClassifier.classify(c), "Set"); }
重载方法的选择是在编译时决定的(即为静态选择,而覆盖方法的选择是在运行时选择的,即动态选择),如果被重载的方法具有相同的参数个数,并且参数类型之间具有继承关系(如上例参数类型Set继承Collection),那么可能导致问题。
List的remove(int)、remove(Object)使用了重载,对List<Integer>类型,在调用remove()方法时应注意区分:
@Test public void testList(){ List<Integer> list=new ArrayList<Integer>(); //-1,0,1将被自动转型为Integer类型 list.add(-1); list.add(0); list.add(1); //因为参数为int类型的1,所以会调用list.remove(int) Assert.assertEquals(list.remove(1), Integer.valueOf(0)); //因为参数为Integer类型,所以会调用list.remove(Object) Assert.assertEquals(list.remove(Integer.valueOf(1)), true); }
使用方法重载的基本原则:
1.重载的方法应具有不同的参数个数
2.如果重载的方法具有相同的参数个数,那么参数的数据类型之间不应有继承关系
3.使用不同名称的静态工厂方法,以避免多个重载的构造函数
4.如果无法避免重载的方法参数个数相同,并且参数之间具有继承关系。那么应调用同一个重载方法,以保证所有的重载方法实现相同的功能。如因为JDK5增加了CharSequence接口,所以String不可避免的出现了方法重载contentEquals(StringBuffer),contentEquals(CharSequence)。但是前者直接调用后者进行比较(String,StringBuffer都实现了CharSequence接口)
5.不要重载具有变长参数的方法