`
frank-liu
  • 浏览: 1680974 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java generic 中通配符的几点理解

    博客分类:
  • java
阅读更多

置换原则

结合Java本身的一些面向对象的特性,我们很容易理解这么一个置换原则:

一个指定类型的变量可以被赋值为该类型的任何子类;一个指定某种类型参数的方法可以通过传入该类型的子类来进行调用。

总的来说,就是说我们使用的任何类型变量都可以用该类型的子类型来替换。

 

泛型中一种错误的继承关系

在泛型的编程中,我们考虑到子类型关系的时候,容易把一种关系给弄混淆,并错误的采用置换原则。

比如说:

 

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<Number> nums = ints; // compile error

 在这段代码中,我们看到类型参数Integer是Number的子类型,就容易想当然的认为List<Integer>也是List<Number>的子类。实际上并不是。所以才会导致类型不匹配,产生编译时错误。

    有点时候,我们觉得,这样的转换看似不能用到一个好处,就是利用对象之间继承的关系。要是我们能有一个列表,它既能处理某种类型的数据,还能处理该类型的所有子类型的数据,这样岂不是既能用到泛型的好处又可以用到对象关系的好处么?于是在这里就引出了通配符(wildcard)。

 

通配符(Wildcard)

在Java类库中Collection接口定义中有一个用到通配符的方法:

interface Collection<E> {
...
public boolean addAll(Collection<? extends E> c);
...
}
在addAll方法的描述里,可以接受Collection类型的参数。其中Collection中的类型参数可以为任何继承E的子类型。

因此,我们可以在实际代码中这么使用:

List<Number> nums = new ArrayList<Number>();
List<Integer> ints = Arrays.asList(1, 2);
List<Double> dbls = Arrays.asList(2.78, 3.14);
nums.addAll(ints);
nums.addAll(dbls);

 在代码中我们可以看到,List<Integer>和List<Double>都是Collection<? extends Number>类型的子类。所以上面的方法中可以将Integer和Double两种类型的List传入到方法中。

通配符使用限制1:

使用通配符的泛型数据类型比较有意思,既然前面我们可以将其作为方法声明的参数,那么是否可以将它作为一个变量类型来直接创建变量呢?

看如下代码:

List<? extends Number> nums = new ArrayList<Integer>(); //compile error
 实际上上面这段代码是编译通不过的。

 

通配符使用限制2:

既然不能用来直接创建变量对象,那么再看下面这段代码:

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile error

 这段代码的第5行会导致编译错误。在第4行代码中,我们将ints赋值给nums,表面上nums声明为一个List<Integer>的父类型,所以第4行编译正常。为什么第5行代码会出错呢?表面上看来,既然nums类型可以接受继承自Number的所有参数,那加一个Double类型的数据应该是没问题的。实际上我们再考虑一下这样会带来的问题:

nums本来引用的是一个继承自该类型的List<Integer>,如果我们允许加入Double类型的数据的话,那么ints这个Integer的List里面就包含了Double的数据,当我们使用ints的时候,和我们所期望的只包含Integer类型的数据不符合。

 

因此,这段代码也说明了一个问题,就是在? extends E这种通配符引用的数据类型中,如果向其中增加数据操作的话会有问题。所以向其中增加数据是不允许的。但是我们可以从其中来读取数据。

 

总结:

1:通配符修饰的泛型不能用来直接创建变量对象。

2:通配符修饰相当于声明了一种变量,它可以作为参数在方法中传递。这么做带来的好处就是我们可以将应用于包含某些数据类型的列表的方法也应用到包含其子类型的列表中。相当于可以在列表中用到一些面向对象的特性。

 

 

ps:

实际上通配符的使用既包括? extends也包括? super的应用。累了,下回继续更新:)

 

0
0
分享到:
评论

相关推荐

    Java Generic 介绍 (pdf)

    通过深入理解和熟练应用Java泛型,开发者可以编写出更健壮、可维护的代码,减少潜在的类型错误,提高代码质量。对于阅读给定的“generic.pdf”文档,可以期待更详细的泛型用法示例、最佳实践和深入解析。

    Java - Generic

    在Java编程语言中,泛型(Generic)是一个强大的特性,它允许我们在编译时检查类型安全,并且可以消除运行时的类型转换。泛型引入的主要目的是提高代码的重用性、安全性和效率,同时减少类型转换的繁琐工作。这篇...

    Generic_MT4_java_generic_mt4_

    标题中的"Generic_MT4_java_generic_mt4_"暗示了一个与MetaTrader 4 (MT4)交易平台相关的编程项目,可能是一个自定义的智能交易系统(Expert Advisor,EA)或指标,使用了Java语言,并且具有通用性。这个“Generic_...

    Java1.5泛型指南中文版(Java1.5 Generic Tutorial)

    Java1.5泛型指南中文版(Java1.5 GenericTutorial)

    Generic Variance java 源码

    Generic Variance java 源码

    Generic Stack java 源码

    Generic Stack java 源码

    java-generic.rar_泛型

    在《java-generic.rar》压缩包中包含的《java generic.pdf》文件,很可能是详细阐述了以下几个关于Java泛型的核心知识点: 1. **类型参数化**:泛型的核心在于类型参数化,这使得我们可以在定义类、接口和方法时...

    Generic Programming for Scientific Computing in C++, Java, and C#

    ### 泛型编程在科学计算中的应用:C++、Java与C#的比较 #### 摘要概览 本文是一篇关于泛型编程在科学计算领域应用的研究论文。研究对比了Java、C#和C++三种语言在实现泛型(参数化类型)方面的表现,并重点介绍了...

    Generic Generic 16BW-5 驱动

    这个描述虽然简洁,但我们可以从中推测出几个关键知识点: 1. **硬件兼容性**:"Generic Generic 16BW-5"可能是一个具有广泛兼容性的硬件设备,可能是打印机、扫描仪、网络适配器或其他类型的外设。"Generic"这个词...

    java泛型数组

    通过上述讨论,我们可以得出以下几点结论: 1. **泛型数组的创建**:在 Java 中,直接创建泛型数组是不可能的,而应当采用 `Array.newInstance` 或其他替代方案。 2. **类型擦除的影响**:Java 泛型在运行时会被擦除...

    java高手真经 光盘源码

    java高手真经 全光盘源代码 打包rar 第1部分(2个程序包) HelloWorld.zip 01.Java入门样例Hello...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性

    C语言头文件 GENERIC

    C语言头文件 GENERICC语言头文件 GENERICC语言头文件 GENERICC语言头文件 GENERICC语言头文件 GENERICC语言头文件 GENERICC语言头文件 GENERICC语言头文件 GENERICC语言头文件 GENERICC语言头文件 GENERICC语言...

    generic 22bw1

    标题中的"generic 22bw1"可能是指一个软件或者硬件产品的版本标识,其中"generic"通常代表通用或标准的意思,而"22bw1"可能是这个产品版本的特定编号或者代号,可能是为了区分不同的迭代或者更新。在IT行业中,这种...

    Generic22BW.zip

    如果"Generic22BW"是应用程序,它可能涵盖各种IT领域的知识点。比如,它可能是一个基于Web的应用,涉及HTML、CSS、JavaScript等前端技术,以及Node.js、Python或PHP等后端语言。如果是移动应用,那么它可能涉及到...

    11.4java-泛型(Generic).md

    11.4java-泛型(Generic)

    打印机驱动Generic 22BW

    本文将深入探讨“打印机驱动Generic 22BW”,特别是针对震旦品牌的打印机,包括Generic 16/21/22型号的相关知识点。 首先,我们要理解什么是“Generic”驱动。在打印机驱动中,“Generic”通常指的是通用驱动程序。...

    61850的Java端

    总结来说,“61850的Java端”涉及了以下几个核心知识点: 1. Java编程语言的基本概念和特性。 2. IEC 61850协议的结构、数据模型和服务。 3. MMS协议的报文解析和生成。 4. GOOSE和SV实时数据传输机制。 5. Java ...

Global site tag (gtag.js) - Google Analytics