当前位置: 代码迷 >> 综合 >> Effective java 慎用重载
  详细解决方案

Effective java 慎用重载

热度:19   发布时间:2023-09-29 01:56:41.0

试图根据一个集合是Set、Liist、还是其他的集合类型,对它进行分类的程序:

 

public class CollectionClassifier {public static String classify(Set<?> s) {return "Set";}public static String classify(List<?> l) {return "List";}public static String classify(Collection<?> c) {return "Unknown Collection";}public static void main(String[] args) {Collection<?>[] collections = {new HashSet<String>(),new ArrayList<BigInteger>(),new HashMap<String, String>().values()};for(Collection<?> c : collections) {System.out.println(classify(c));}}
}

期望打印出的是Set,List,Unknown Collection,但实际上却是三个Unknown Collection。classify方法被重载,而要调用哪个重载方法是在编译时做出决定的,而三个集合的参数在编译时的类型都是Collection<?>,虽然运行时的类型不同,但不影响对重载方法的选择。所以唯一适合的方法是参数为Collection<?>的那一个。

与覆盖方法不同,覆盖方法的选择是动态的,选择的依据是运行时的类型,而不管编译时的类型是什么。

 

修正方案,使用单个方法替换重载的classify方法,也就是不使用重载机制:

public static String classify(Collection<?> c) {return c instanceof Set ? "Set" :c instanceof List ? "List" : Unknown Collection";
}

 

ObjectOutputStream类,对于每个基本类型,以及几种引用类型,它的write方法的命名都不一样,如writeInt,writeBoolean,writeLong等。这是一种好的实践。

 

Java 1.5发行后,出现了自动装箱,引起的一些问题:

 

public class SetList {public static void main(String[] args) {Set<Integer> set = new TreeSet<Integer>();List<Integer> list = new ArrayList<Integer>();for(int i = -3; i < 3; i++) {set.add(i);list.add(i);}for(int i = 0; i < 3; i++) {set.remove(i);list.remove(i);}System.out.println(set + " " + list);}}

打印的结果是:

Effective java 慎用重载

原因是List有remove(int)和remove(Object)方法,Set只有一个remove(Object)方法,list.remove(i)调用的是remove(int)方法,所以导致这样的结果。

修改成list.remove((Integer) i);就能使结果一致了。

 

对于多个具有相同参数数目的方法来说,应该尽量避免重载方法,对于构造器,可以选择静态工厂,避免参数只需经过类型转换就可以被传递给不同的重载方法,如果不能避免,应保证传递相同参数,所有的重载方法行为一致,否则对程序员有效使用重载方法会造成困难。

  相关解决方案