泛型机制常用的参数有3个:
“?”代表任意类型。如果只指定了<?>,而没有extends,则默认是允许任意类。
extends关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类。
super关键字声明了类型的下界,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至Object
前提
Fruit是Apple和Orange的超类。
本章通过java代码逐一分析泛型参数的意义和区别
extends参数:
[java]
public void extend(List<? extends Fruit> list, Fruit fruit){
Fruit now = list.get(0);
System.out.println("now==>" + now);
// Apple a = list.get(0); 无法通过编译
Object o = list.get(0);
System.out.println(o);
// list.add(fruit); //这句话无法编译
// list.add(new Object()); // 无法通过编译
list.add(null);//这句可以编译,因为null没有类型信息
}
在上面的例子中,可以明确从list中取得的记录一定是Fruit,但是无法确定是Apple,list除了传入null外,不能添加其他任何参数;分析原因前先看以下的例子:
[java]
public void testExtendType(){
List<? extends Fruit> list = new ArrayList<Fruit>();
List<? extends Fruit> list2 = new ArrayList<Apple>();
List<? extends Fruit> list3 = new ArrayList<Orange>();
extend(list2, new Apple());
}
从以上代码可以看出:
extends关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类,List<? extends Fruit> 可以指向 ArrayList<Fruit>()、ArrayList<Apple>()、 ArrayList<Orange>()等。现在如果传入的参数list为new ArrayList<Apple>(),则此时你向此list中添加
Fruit,则肯定报错。而读取数据时,不管list是什么类型,读取的数据肯定都是Fruit,同时Fruit也是Object。
通过以上的分析,知道直接往继承extends中的列表中添加记录是不行的,那么如何向extends修饰的list中添加记录,可以使用泛型方法来达到目的:
[java]
public <T extends Fruit> void extendType2(List<T> list, T date){
list.add(date);
}
调用示例如下:
[java]
public void testExtendType2(){
List<Apple> list = new ArrayList<Apple>();
extendType2(list,new Apple());
}
super参数
super用的不多,只简单介绍一下。
[java]
public void superType(List<? super Apple> list, Apple apple){
Object o = list.get(0);
System.out.println(o);
// Apple a = list.get(0); // 不能编译
// Apple apple = list.get(0); // 不能编译
list.add(apple);
// list.add( new Object()); // 不能编译
// list.add( new Fruit()); // 不能编译
}
在以上代码中,从list中读取的记录无法确定是任何类型(除Object),list除了添加Apple外,不能添加任何类型的对象(包括Object)。分析原因前先看以下代码:
[java]
public void testSuperType(){
List<? super Apple> list = new ArrayList<Apple>();
List<? super Apple> list2 = new ArrayList<Fruit>();
superType(list2, new Apple());
}
super关键字声明了类型的下界,表示参数化的类型是所指定的类型,或者是此类型的父类型,直至Object。List<? super Apple > 可以引用 List<Apple>,也可以引用 List<Fruit>,所以无法保证list中都是Apple,但是可以保证,所有list引用的都是Apple的父类,所有向此列表中添 加Apple是没有问题的,而很显然你向List<Fruit>、List<Apple>中添加Object、Fruit对象, 肯定失败,只能够添加Apple。
?参数
“?”代表任意类型。?可以看做 ? extends Object 的缩写。
[java]
public void wideCardType(List<?> list, Fruit fruit ){
Object o = list.get(0);
System.out.println(list.get(0));
// list.add(fruit); // 不能编译
// list.add(new Object()); // 不能被编译
}
[java]
public void testWideCardType(){
/**
* ? 可以看做 ? extends Object 的简化版
*/
List<?> list = new ArrayList<Fruit>();
List<?> list2 = new ArrayList<Apple>();
List<?> list3 = new ArrayList<Object>();
wideCardType(list,new Fruit());
}
List<? super Object> 可以引用 List<任何类型>,而Object是所有的对象的祖先,此list只能添加Object类型对象。
extends和super意义记忆的技巧
? extends A: ?继承A,?是A的子类,或者?是A本身
? super B: ?是B的父类,或者?是B本身
- Java基础教程:泛型基础
Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...
- Java基础 -- 深入理解泛型
一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 而泛型很好的解决了这个问题,这也是Java SE5的重大 ...
- Java 基础篇之泛型
背景 在没有泛型前,一旦把一个对象丢进集合中,集合就会忘记对象的类型,把所有的对象都当成 Object 类型处理.当程序从集合中取出对象后,就需要进行强制类型转换,这种转换很容易引起 ClassCas ...
- Java基础教程(21)--泛型
一.为什么使用泛型 泛型意味着编写的代码可以被很多不同类型的对象所重用.例如,我们不希望为存放String和Integer对象的集合设计不同的类.现在的ArrayList类可以存放任何类型的对象, ...
- JAVA基础_自定义泛型
泛型的来源 在Java中,泛型借鉴了C++的模版函数,从而引入了泛型. C++泛型 int add(int x,int y){ return x + y; } float add(float x.fl ...
- 【java基础学习】泛型
泛型 1. 泛型类(声明的泛型类型静态方法不能使用) class Tools<T>{ private T t; public void set(T t){ this.t = t; } pu ...
- 【Java基础总结】泛型
泛型实现了参数化类型的概念,使代码可以应用于多种类型. 1. 泛型类 声明的泛型类型静态方法不能使用 class Tools<T>{ private T t; public void se ...
- java基础之对象当做参数传进方法的堆栈内存解析
值类型当做参数传进方法: 引用类型对象当做参数传进方法: String字符串当做参数传进方法:
- 一天一个Java基础——泛型
这学期的新课——设计模式,由我仰慕已久的老师传授,可惜思维过快,第一节就被老师挑中上去敲代码,自此在心里烙下了阴影,都是Java基础欠下的债 这学期的新课——算法设计与分析,虽老师不爱与同学互动式的讲 ...
随机推荐
- 处理 javax.el.ELException: Failed to parse the expression 报错
在JSP的表达式语言中,使用了 <h3>是否新Session:${pageContext.session.new}</h3> 输出Session是否是新的,此时遇到了 j ...
- retry.RetryInvocationHandler (RetryInvocationHandler.java:invoke(140)) - Exception while invoking getFileInfo of class ClientNamenodeProtocolTranslatorPB over bdata236/192.168.1.236:9000 after 3 fail
报错信息如下 -- ::, INFO [main]: retry.RetryInvocationHandler (RetryInvocationHandler.java:invoke()) - Exc ...
- Jquery Uploadify多文件上传实例
jQuery Uploadify开发使用的语言是java. 详细的相关文档,可以参考官网的doc:http://www.uploadify.com/documentation/ 官网的讲解还是很详细的 ...
- 解决微信浏览器video全屏的问题
解决微信浏览器video全屏的问题 在微信浏览器里面使用video标签,会自动变成全屏,改成下面就好了,起码可以在video标签之上加入其他元素. <video id="videoID ...
- 从request中读数据流
ServletInputStream servletInputStream = reqeust.getInputStream(); int len=0; int size=reqeust.getCon ...
- hbase_学习_01_HBase环境搭建(单机)
一.前言 本文承接上一篇:hadoop_学习_02_Hadoop环境搭建(单机) ,主要是搭建HBase的单机环境 二.环境准备 1.说明 hbase 的下载来源有: 官方版本:http://arc ...
- php常用函数htmlspecialchars、strip_tags、addslashes解析
本文章向大家介绍php开发中经常使用到的字符串函数htmlspecialchars.strip_tags.addslashes的使用方法及他们之间的区别,需要的朋友可以参考一下. 1.函数strip_ ...
- SQL的CASE表达式用法
case 表达式从SQL-92标准开始引入,因此是不依赖于具体的数据库技术,可提高SQL代码的可移植性. case表达式注意事项: 1. 统一各个分支返回数据类型,并保证各个when字句的排他性,因为 ...
- Android 内存监测工具 DDMS --> Heap
用 Heap监测应用进程使用内存情况的步骤如下: 1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的: 2. 将手机通过USB链接至电脑,链接时需要确认 ...
- Smooks:xml-to-java
引言: Smooks是一个开源的Java框架,用于处理“数据事件流”.它常常被认为是一个转换框架并以此被用于好几个产品和项目中,包括JBoss ESB(以及其它ESB).然而究其核心,Smooks未提 ...