zoukankan      html  css  js  c++  java
  • [转]《Java Generics and Collections》读书笔记一:java泛型基本问题

    转自:http://www.diybl.com/course/3_program/java/javaxl/20071220/92739.html

    1. Java的泛型实现采用"擦除法".
    编译器为我们完成类型擦除和必要的类型转换, 在运行时,每个泛型类只有一种类型. 具体地说, List<Integer>, List<String> 和 List<List<String>> 在运行时都将具有相同的类型: List
    //泛型是1.5中引入的一个新的概念,由于不用进行强制转换类型了,所以具有较高的安全性和易用性。因为泛型其实只是在编译器中实现的而虚拟机并不认识泛型类项,所以要在虚拟机中将泛型类型进行擦除。也就是说,在编译阶段使用泛型,运行阶段取消泛型,即擦除。 擦除是将泛型类型以其父类代替,如String 变成了Object等。其实在使用的时候还是进行带强制类型的转化,只不过这是比较安全的转换,因为在编译阶段已经确保了数据的一致性。
    2. Boxing and Unboxing 自动装箱 和 自动拆箱
    特别注意在 == 比较时, 自动装箱和自动拆箱所造成的影响, 如下面代码:
    public static int sum(List<Integer> ints) {
      int s = 0;
      for (int n : ints) { s += n; }
      return s;
    }
    public static Integer sumInteger(List<Integer> ints) {
      Integer s = 0;
      for (Integer n : ints) { s += n; }
      return s;
    }
    上面两个方法实现相同的功能, 前者采用Java 5的新特性, 相比下效率会比后者快大概一倍.??
    List<Integer> bigs = Arrays.asList(100,200,300);
    assert sumInteger(bigs) == sum(bigs);  // 应用自动拆箱, 比较两个int, 结果为true
    assert sumInteger(bigs) != sumInteger(bigs);  // 比较Integer对象, 结果为false
    上面代码还比较好理解, Java在实现装箱时采用了缓存机制, 缓存-128 ~ 127之间的整数, ''\u0000'' ~ ''\u007f''之间的char类型, byte类型, 以及boolean可以提高效率. 对其它范围的数据, Java标准也允许对其进行缓存, 所以上面的第二个断言有可能会失败.
    List<Integer> smalls = Arrays.asList(1,2,3);
    assert sumInteger(smalls) == sum(smalls);  // 比较int, 结果肯定为true
    assert sumInteger(smalls) == sumInteger(smalls);  // 由于缓存, 两个Integer其实是同一个对象, 所以结果也为true
    结论: 不要依赖于自动装箱和自动拆箱的缓存机制, 对于对象的比较, 任何时候都应该使用equals方法而不是==.


    3. 泛型方法和可变参数方法(Varargs)
    class Lists {
      public static <T> List<T> toList(T... arr) {
        List<T> list = new ArrayList<T>();
        for (T elt : arr) list.add(elt);
        return list;
      }
    }
    上面是使用泛型和可变参数的一个简单例子, 调用该方法时, 我们可以传入连续的几个参数, 也可以传入一个参数的数组. 其实可变参数方法唯一的好处就是方便, 它让我们不用自己把实参打包到一个数组中. Java编译器为我们完成这一工作, 实际上, 在运行时, 上面方法其实就是使用参数的数组来实现.
    调用泛型方法时, 如果参数类型不明确, 我们就需要明确地指出类型信息, 否则就会引起"未检查的警告消息", 使用如下的格式:
    List<Integer> ints = Lists.<Integer>toList();
    List<Object> objs = Lists.<Object>toList(1, "two");
    另外, Java的语法要求: 在使用明确的类型调用方法时, 必需使用带有 "." 的格式. 以上面Lists类为例, 即使是在Lists类内部的方法中, 也不可以使用 List<Integer> ints = <Integer>toList(); 而必需使用 List<Integer> ints = Lists.<Integer>toList();

  • 相关阅读:
    docker镜像制作及上传到远端镜像仓库
    mysql索引进阶
    电子商务需要用到香港服务器吗?
    golang module goland 配置代理
    nginx做linux服务时,日志有权限提示没权限(nginx: [emerg] open() "/home/www/log/error.log" failed)
    Yaml 、Json 、Dict 之间的转化
    CodeSmith .NET三层架构模板
    C#获取26个英文字母
    基于PCASClass.js和layui.js的城市三级联动
    MySQL变量的使用
  • 原文地址:https://www.cnblogs.com/apigiraffe/p/2685046.html
Copyright © 2011-2022 走看看