泛型机制常用的参数有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基础欠下的债 这学期的新课——算法设计与分析,虽老师不爱与同学互动式的讲 ...
随机推荐
- 关于spring事务注解
关于事务的注解常用如下1.如果有事务, 那么加入事务, 没有的话新建一个(默认情况下),也就是当我们要开启事务的时候才用,即有数据库有增删改操作@Transactional(rollbackFor=E ...
- Victor/ArrayList/LinkedList/Stack/CopyOnWriteArrayList 区别
Victor:采用数组的方式存储数据,与ArrayList相同,线程安全.性能比ArrayList差 ArrayList:采用数据的方式存储数据,线程不安全.ArrayList使用数组来存储数据,使用 ...
- 超快的maven setting文件
<?xml version="1.0"?> <settings> <localRepository>/home/yizhen/.m2/repos ...
- Codeforces Round #260 (Div. 2) A , B , C 标记,找规律 , dp
A. Laptops time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- c语言代码风格2
1.注释 注释的目的是为了说明做了什么,而不是怎么做,所以注释表达应该准确而又简洁.注释要放在被注释内容的上方或右方.注释一般采用/*.........*/或//........ 对代码源文件和函数应 ...
- STL list链表的用法详解
本文以List容器为例子,介绍了STL的基本内容,从容器到迭代器,再到普通函数,而且例子丰富,通俗易懂.不失为STL的入门文章,新手不容错过! 0 前言 1 定义一个list 2 使用list的成员函 ...
- SSH三大框架的搭建整合(struts2+spring+hibernate)(转)
原文地址:http://blog.csdn.net/kyle0349/article/details/51751913 尊重原创,请访问原文地址 SSH说的上是javaweb经典框架,不能说100% ...
- Python基础-修改excel中内容
from xlutils.copy import copy import xlrd import os #1.打一要修改的excel #2.再打开另一个excel #3.把第一个excel里面修改东西 ...
- MySQL--Basic(一)
停止与启动服务命令: net stop mysql net start mysql 修改MySQL提示符: mysql>prompt \u@\h \d> MySQL语句规范: 关键字与函数 ...
- MySQL丨删除一张表小常识
在MySQL里面 ,对于删除一张表里面的所有内容有两种语句: 1.delete from table_name; 2.truncate table table_name; 解析:以上两种方式都可以删除 ...