zoukankan      html  css  js  c++  java
  • 第41条:慎用重载

    试图根据一个集合是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);
        }
    
    }

    打印的结果是:

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

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

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

  • 相关阅读:
    EBGAN
    Inception Score
    对称加密系统,攻击方式
    tensorboard的使用
    pip更新后,下载慢,国内更新源
    VSCODE快捷键
    Ajax JS
    ORM操作之Django后台管理、外键、QuerySet、查询sql语句、用户管理
    ORM操作之分类、创建数据库表结构流程、基本操作、操作表结构、字段类型、字段参数
    路由系统 视图 默认数据交互规则 获取用户提交信息
  • 原文地址:https://www.cnblogs.com/13jhzeng/p/5745204.html
Copyright © 2011-2022 走看看