《Java 编程思想》--第十五章:泛型

  1. 一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码
  2. 泛型的概念:使代码能够应用于“某种不具体”的类型,而不是一个具体的接口或类。泛型实现了参数化类型的概念,使代码可以应用于多种类型
  3. 促使泛型出现的原因之一:为了创造容器类。容器,几件事存放要使用的对象的地方。泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性
  4. Java泛型的核心概念:告诉编译器想使用什么类型,然后编译器帮你处理一切细节
  5. 元组:将一组对象直接打包存储于其中的一个单一对象。这个容器对象允许读取其中元素,但是不允许向其中存放新的对象。可以使用继承机制实现更长的元组
    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      public abstract class test{
           public class TwoTuple<A, B>{
               public final A first;
               public final B second;
               public TwoTuple(A a, B b){
                   first = a;
                   second = b;
               }
           }
           
           public class ThreeTuple<A, B, C> extends TwoTuple<A, B>{
               public final C third;
               public ThreeTuple(A a, B b, C c){
                   super (a, b);
                   third = c;
               }
           }
           
      }
  6. 泛型也可以应用于接口,例如生成器--这是一种专门负责创建对象的类
  7. 可以声明ArrayList.class,但是不能声明Array<Integer>.class,而且如下代码:
    1. 1
      2
      3
      4
      5
      public static void main (String[] args){
           Class c1 = new ArrayList<Integer>().getClass();
           Class c2 = new ArrayList<String>().getClass();
           System.out.println(c1 == c2);
      }
      将输出true
  8. Class.getTypeParameters()将返回一个TypeVariable对象数组,表示有泛型声明所声明的类型参数,但是只是用作参数占位符的标识符,并非有用的信息。在泛型代码内部,无法获得任何有关泛型参数类型的信息
  9. Java泛型是使用擦除来实现的,这意味着当你使用泛型时,任何具体的类型信息都被擦除了,你为指导的就是你在使用一个对象。因此,List<String>和List<Integer>在运行时事实上是相同的类型。这两种形式都被擦除成了他们原生类型,即List。
  10. 泛型类型参数将擦除到它的第一个边界(它可能会有多个边界)。擦除不是Java语言的特性,而是它的泛型实现的折中。泛型类型只有在静态类型检查期才出现,在此之后,程序中的所有泛型类型都将被擦除,替换为他们的非泛型上界
  11. 擦除的核心动机是它使得泛化的客户端可以用非泛化的类库来使用,反之亦然,这称为“迁移兼容性”。擦除的主要正当理由是从非泛化的代码到泛化的代码的转变过程,以及在不破坏现有类库的情况下,将泛型融入java语言中
  12. 擦除的代价是显著的:泛型不能用与显式地引用运行时类型的操作之中,例如转型、instanceof操作和new表达式。因为所有关于参数的类型信息都丢失了,你只是看起来好像拥有有关参数的类型信息
  13. 不能创建泛型数组,一般的解决方案是在任何想要创建泛型数组的地方都是用ArrayList
  14. 因为擦除移除了类型信息,所以,可以用无界泛型参数调用的方法只是那些可以用Object调用的方法
  15. 与数组不同,泛型没有内建的协变类型。这是因为数组在语言中是完全定义的,因此可以内建了编译期和运行时的检查,但是在使用泛型时,编译期和运行时系统都不知道你想用什么类型做些什么,以及应该采用什么样的规则
  16. 无界通配符<?>看起来意味着“任何事物”,因此使用无界通配符好像等价于使用原生类型
    1. 编译期很少关心使用的是原生类型还是<?>,在这种情况中<?>可以被认为是一种装饰,但是它依旧很有价值,他在声明:"我想用java泛型来编写这段代码,我在这里并不是要用原生类型,但是在当前这种情况下,反省参数可以持有任何类型"
    2. 由于泛型参数将擦除到它的第一个边界,因此List<?>看起来等价于List<Object>,而List实际上也是List<Object>--除非这些语句都不为真.List实际上表示"持有任何Object类型的原生List",而List<?>表示"具有某种特定类型的非原生List,只是我们不知道那种类型是什么"
  17. 不能将基本类型作为类型参数
  18. 由于擦除的原因,重载方法将产生相同过的类型签名,所以无法如下重载
  19. 古怪的循环泛型(CRG),指类相当古怪的出现在它自己的基类中这一事实."我在创建一个新类,它继承自一个泛型类型,这个泛型类型接受我的类的名字作为其参数"。CRG的本质:基类用导出类替代其参数,这意味着泛型基类变成了一种其所有导出类的公共功能的模板,但是这些功能对于其所有参数和返回值,将使用导出类型。也就是说,在所产生的类中将使用确切类型而不是基类型。
  20. 自限定类型的价值在于它们可以产生协变参数类型--方法参数类型会随子类而变化
  21. 由于擦除的原因,将泛型应用于异常是非常受限的。catch语句不能捕获泛型类型的异常,因为在编译期和运行时都必须知道异常的确切类型。泛型类也不能直接或间接继承自Throwable
  22. 混型:最基本的概念是混合多个类的能力,以产生一个可以表示混型中所有类型的类。其价值之一是他们可以将特性和行为一致地应用于多个类之上
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值