泛型机制常用的参数有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基础 -- 泛型之泛型参数的更多相关文章

  1. Java基础教程:泛型基础

    Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...

  2. Java基础 -- 深入理解泛型

    一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 而泛型很好的解决了这个问题,这也是Java SE5的重大 ...

  3. Java 基础篇之泛型

    背景 在没有泛型前,一旦把一个对象丢进集合中,集合就会忘记对象的类型,把所有的对象都当成 Object 类型处理.当程序从集合中取出对象后,就需要进行强制类型转换,这种转换很容易引起 ClassCas ...

  4. Java基础教程(21)--泛型

    一.为什么使用泛型   泛型意味着编写的代码可以被很多不同类型的对象所重用.例如,我们不希望为存放String和Integer对象的集合设计不同的类.现在的ArrayList类可以存放任何类型的对象, ...

  5. JAVA基础_自定义泛型

    泛型的来源 在Java中,泛型借鉴了C++的模版函数,从而引入了泛型. C++泛型 int add(int x,int y){ return x + y; } float add(float x.fl ...

  6. 【java基础学习】泛型

    泛型 1. 泛型类(声明的泛型类型静态方法不能使用) class Tools<T>{ private T t; public void set(T t){ this.t = t; } pu ...

  7. 【Java基础总结】泛型

    泛型实现了参数化类型的概念,使代码可以应用于多种类型. 1. 泛型类 声明的泛型类型静态方法不能使用 class Tools<T>{ private T t; public void se ...

  8. java基础之对象当做参数传进方法的堆栈内存解析

    值类型当做参数传进方法: 引用类型对象当做参数传进方法: String字符串当做参数传进方法:

  9. 一天一个Java基础——泛型

    这学期的新课——设计模式,由我仰慕已久的老师传授,可惜思维过快,第一节就被老师挑中上去敲代码,自此在心里烙下了阴影,都是Java基础欠下的债 这学期的新课——算法设计与分析,虽老师不爱与同学互动式的讲 ...

随机推荐

  1. windows下Scrapy爬虫框架环境搭建

    1.   安装python 根据你的需求下载python安装包,安装python(本文基于python27)https://www.python.org/downloads/ 下载完安装默认安装路径, ...

  2. Hadoop- 集群启动详解

    NameNode启动过程详解 第一次启动:HDFS格式化后,生成fsimage文件 hdf

  3. Spark- 优化后的 shuffle 操作原理剖析

    在spark新版本中,引入了 consolidation 机制,也就是说提出了ShuffleGroup的概念.一个 ShuffleMapTask 将数据写入 ResultTask 数量的本地文本,这个 ...

  4. 英语发音规则---ir字母组合发音规律

    英语发音规则---ir字母组合发音规律 一.总结 一句话总结: 这个字母组合通常在单词中读[ɜː]:girl /gɜːl/ n. :shirt /ʃɜːt/ n. girl /gɜːl/ n. 女孩 ...

  5. Delphi - 数组 详解

    技术交流,DH讲解. 首先我们要知道什么是数组?数组是一堆相同特性数据的一个集合,也就是每个元素的类型必须是一样的,当然在其他一些弱语法的语言里面,数组的元素可以千奇百怪. 例子: ? 1 2 3 4 ...

  6. UniDAC 安装教程

    翻译: 1.解压后把UniDAC文件夹直接复制到你专门用来存放第三方控件的地方(这一步根据自己的喜好,可以跳过这一步)2.在UniDAC\Source\Delphi21文件夹中找到Make.bat文件 ...

  7. Winform开发入门集中培训系列文章

    最近有个培训,写PPT不如写博客了,共享是程序猿的职业情操吧,因此,本人准备写一个Winform开发的系列文章,对于初级开发者来说,应该比较有用,写作当中不免错误或不成熟的地方,看到的朋友请留言指出, ...

  8. 表达式计算-----------eval()运算符

    1.java的eval()方法(或称之为运算符)可以将字符串解析成可以运行的javaScript代码,例如 eval()只有一个参数.如果传入的参数不是一个字符串,那么它会直接返回这个参数.如果传入的 ...

  9. 输入框input内容变化与onpropertychange事件的兼容

    一.输入框常用的几个事件 onblur 元素失去焦点. onchange 域的内容被改变. onclick 当用户点击某个对象时调用的事件句柄. ondblclick 当用户双击某个对象时调用的事件句 ...

  10. ffmpeg avpicture_fill的一些使用

    标签: ffmpegavpicture_fill 2013-05-17 10:03 4713人阅读 评论(1) 收藏 举报  分类: ffmpeg(3)  这个FFMPEG我没找到详细的中文教程,只有 ...