JAVA泛型-通配符

黑马程序员:Java培训、Android培训、iOS培训、.Net培训

JAVA泛型-通配符

一、泛型与继承

有如下的继承关系和以它们为类型参数的泛型:

public class Holder<T>{

T t;

public Holder(){}

public Holder(T at){ t = at;}

public void set(T at){ t = at;}

public T get(){return t; }

}

//有如下代码:

Holder<Apple> apple = new Holder<Apple>(new Apple());

Holder<Fruit> fruit = apple;  //ERROR,因为Holder<Fruit>与Holder<Apple>不同一类型

Holder raw = apple;        //原始类型

raw.set(new Apple());       //only a compile-time warming

可见,尽管泛型的类型参数存在着继承关系,但它们相应的泛型一点关系也没有。

现在有一个问题:能不能将一个涉及Apple的泛型赋给一个涉及Fruit的泛型?这显然不行。因为Apple的的Holder不是Fruit的Holder,不存在向上转型。但,我们如何在这两个类型之间建立某种类型的向上转型关系,这就是通配符的作用。

二、通配符:泛型类型被限定为单一边界

1、<? exteds T >

1)上限通配,也称为:子类型通配符

2)可读作:具有T类型的某种子类作为类型参数的类。

3)但,这不意味:这个类可持有任何T类型的子类。它只能持有T类型的某种子类或T类型。

4)有了子类型通配,使得我们可以安全地获得一个泛型类型对象中的对象(可调用返回类型为T的函索):

Holder rawHolder = new Holder(new Apple());

Holder<Apple> appleHolder = new Holder<Apple>(new Apple());

Holder<Fruit> fruitHolder = new Holder<Fruit>(new Apple());

fruitHolder = appleHolder;  //ERROR

Holder<? extends Fruit> boundedHolder = appleHolder;

boundedHolder = fruitHolder;

Fruit fruit = boundedHolder.get();

Apple apple = (Apple) boundedHolder.get();

5)Holder<? exteds T >可合法指向Holder< T’s subclass >或Holder<T >。这种指向(类型的向上转型)是有代价的:禁止调用任何含有T类型参数的函数(这个T类型转换为“? exteds T”,编译器无法理解)。例如:

Holder<? extends Fruit> boundedHolder = appleHolder;

boundedHolder.set(new Apple()); //ERROR

boundedHolder.set(new Fruit());  //ERROR

2、<? super T>

1)上限通配 ,也称为:超类型通配符

2)读作:具有T类型的某种父类作为类型参数的类。

3)不能对泛型参数给出一个超类型边界,即不能声明为<T super MyClass>

4)有了超类型通配,使得我们可以安全地传递一个类型对象到泛型类型对象中(编译器虽然不知道set()方法内的参数的确切类型,但可用任意T对象<或子类>调用,而不能用T’s supclass)(可调用任何含有T类型参数的函数):

Holder<? super Fruit> boundedHolder = appleHolder;   //ERROR

boundedHolder = fruitHolder;

boundedHolder.set(new Apple()); //

boundedHolder.set(new Fruit());  //

5)Holder<? super T >可合法指向Holder< T’s supclass >或Holder<T >。这个指向也是有代价的:禁止调用返回类型为T的函索(返回的对象类型得不到保证)。

Holder<? super Fruit> boundedHolder = appleHolder;   //ERROR

boundedHolder = fruitHolder;

Fruit fruit = boundedHolder.get();         //ERROR

Apple apple = (Apple) boundedHolder.get();//ERROR

3、<?>

1)无界通配符

2)好像等价使用原生类型

3)它仍然有价值:这是用泛型来编写代码,而不是使用原生类型,只是在当前情况下,泛型参数可以持有任何类型。

4)Holder、Holder<?>和Holder<T>的区别

Holder:表示“持有任何Object类型的原生Holder”

Holder <?>:表示“持有某种类型的非原生Holder,该类型是Object或其子类”

Holder <T>:表示“持有确切类型的非原生Holder”

5)Holder<?>对象:禁止调用任何含有T类型参数的函数,并且调用返回类型为T的函索的返回值只能赋给Object。

Holder<?> unboundedHolder = new Holder<?>)(new Apple());

Object obj = unboundedHolder.get();

unboundedHolder.set(new Apple());  //ERROR

6)Holder与Holder<?>的本质区别:可用任意Object对象调用原始的Holder类的set()。

7)尽管Holder<?>很脆弱,但Holder<?>仍然有它的作用,例如:判断Holder是否包含指定的对象不为空。

public boolean hasNulls(Holder<?> h){

return h.get() == null ||

}

四、泛型继承及应用

1、继承关系

2、泛型类型与通配类型之间的继承关系(E为泛型类型参数,A为类或接口):

? super E :表示E的未知父类;? extends E:表示E的未知子类。

3、应用举例

1)E read(Holder<? extends E> holder){return holder.get();}

Fruit f = meth(new Holder<Apple>(new Fruit()));

Fruit a = meth(new Holder<Apple>(new Apple()));

2)void write(Holder<? super E> holder, E item){ holder.set(item);}

write(new Holder<Apple>, new Apple());  //Apple

write(new Holder<Fruit>, new Apple());   //Apple的supclass

时间: 2024-07-29 14:48:55

JAVA泛型-通配符的相关文章

Java泛型通配符学习 —— Java Generic&#39;s Wildcards

Java Generic's wildcards is a mechanism in Java Generics aimed at making it possible to cast a collection of a certain class, e.g A, to a collection of a subclass or superclass of A. This text explains how. 理解:Java的泛型通配符机制旨在实现集合的类型转换.例如集合A,转换为A的子类集合或

JAVA泛型通配符T,E,K,V区别,网友回复:一文秒懂

先解释下泛型概念泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法.Java语言引入泛型的好处是安全简单. 在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的"任意化","任意化"带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的.对于强制类型转换错误的

Java泛型-- 通配符

转自:http://blog.csdn.net/flfna/article/details/6576394 ———————————————————————————————————————————— 通配符 在本文的前面的部分里已经说过了泛型类型的子类型的不相关性.但有些时候,我们希望能够像使用普通类型那样使用泛型类型: ◆ 向上造型一个泛型对象的引用 ◆ 向下造型一个泛型对象的引用 向上造型一个泛型对象的引用 例如,假设我们有很多箱子,每个箱子里都装有不同的水果,我们需要找到一种方法能够通用的处

java泛型通配符?

转自:http://www.linuxidc.com/Linux/2013-10/90928.htm T  有类型 ?  未知类型 一.通配符的上界 既然知道List<Cat>并不是List<Anilmal>的子类型,那就需要去寻找替他解决的办法, 是AnimalTrianer.act()方法变得更为通用(既可以接受List<Animal>类型,也可以接受List<Cat>等参数).在java里解决办法就是使用通配符"?",具体到Anim

理解Java泛型 通配符 ? 以及其使用

什么是泛型: 泛型从字面上理解,是指一个类.接口或方法支持多种类型,使之广泛化.一般化和更加通用.Java中使用Object类来定义类型也 能实现泛型,但缺点是造成原类型信息的丢失,在使用中容易造成ClassCastException. Java泛型带到的好处: 使得一个类或方法中的类型参数化,最终达到代码复用的效果.( 不使用泛型,你可能需要每种情况的类或方法都要定义一遍 ) 实现类型检查的功能,避免ClassCastException.(这是相对于使用Object类型实现泛型而言.因为我可以

Java泛型 通配符? extends与super

本文来源:https://i.cnblogs.com/EditPosts.aspx?opt=1 感谢博主.本文仅供参考学习. Java 泛型 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object extends 示例 static class Food{} static class Frui

JAVA泛型通配符T,E,K,V区别,T以及Class&lt;T&gt;,Class&lt;?&gt;的区别

1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法.Java语言引入泛型的好处是安全简单.在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的.对于强制类型转换错误的情况,编译器可能不提示错

JAVA 泛型通配符 ? EXTENDS SUPER 的用法

1. <? extends Hero> ArrayList heroList<? extends Hero> 表示这是一个Hero泛型或者其子类泛型heroList 的泛型可能是HeroheroList 的泛型可能是APHeroheroList 的泛型可能是ADHero所以 可以确凿的是,从heroList取出来的对象,一定是可以转型成Hero的 但是,不能往里面放东西,因为放APHero就不满足<ADHero>放ADHero又不满足<APHero> 2.

java泛型---通配符,泛型嵌套

package generic; import java.util.ArrayList; import java.util.List; /** * ? -->通配符,类型不确定,用于声明 变量|形参 上 * 不能用在: * 1,创建对象 * 2,创建泛型类 .泛型方法.泛型接口上 * */ public class WildcardTest { public static void main(String[] args) { //声明 List<?> list = new ArrayLi

Java泛型通配符以及限定

摘抄笔记 A:泛型的限定 /* * 将的酒店员工,厨师,服务员,经理,分别存储到3个集合中 * 定义方法,可以同时遍历3集合,遍历三个集合的同时,可以调用工作方法 */ import java.util.ArrayList; import java.util.Iterator; public class GenericTest { public static void main(String[] args) { //创建3个集合对象 ArrayList<ChuShi> cs = new Arr