泛型机制常用的参数有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. 2014年的暑假ACM之旅!

    致未来的我: 回到学校了,又开始了繁忙的生活! 虽然每天都不太轻松,但还是蛮有乐趣的,一起讨论某道题或者某种算法时挺开心的.@我.@姜维波.@曹彦宝.@李岩.@张永宏 继续这样下去,直到这个暑假的结束 ...

  2. 机器学习——支持向量机(SVM)

    机器学习--支持向量机(SVM) 支持向量机(Support Vector Machine)广泛地应用于分类问题,回归问题和异常检测问题.支持向量机一个很好的性质是其与凸优化问题相对应,局部最优解就是 ...

  3. 仿联想商城laravel实战---5、无刷新的增删改查(动态页面更新的三种方式(html))

    仿联想商城laravel实战---5.无刷新的增删改查(动态页面更新的三种方式(html)) 一.总结 一句话总结: 直接js增加删除修改html 控制器直接返回处理好的页面 用双向绑定插件比如vue ...

  4. java:类集回顾

    1.类集设置的主要目的:动态的对象数组 2.类集中有以下几个接口: Collection:是存放单值的最大父接口 |- List接口:里面的内容是允许重复的 |- ArrayList, Vector, ...

  5. css 多行文本以...代替

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. SpringBoot_03_依赖本地jar

    一.方法一 1.说明 用Maven打到本地仓库,然后直接引入 2.参考资料 Springboot 打Jar包,Maven完美解决本地Jar包自动打入Springboot Jar包中 3.执行maven ...

  7. Tomcat_异常_02_IOException while loading persisted sessions: java.io.EOFException

    异常原因: EOFException表示输入过程中意外地到达文件尾或流尾的信号,导致从session中获取数据失败. 这是由于tomcat上次非正常关闭时有一些活动session被持久化(表现为一些临 ...

  8. AngularJS-Basic(一)

    MVC:作为DataModel的$scope 依赖注入DI 模块化Module Service Filter Two way DateBinding Directive Unit Testing&am ...

  9. java--xml文件读取(SAX)

    SAX解析原理: 使用Handler去逐个分析遇到的每一个节点 SAX方式解析步奏: 创建xml解析需要的handler(parser.parse(file,handler)) package com ...

  10. uoj problem 21 缩进优化

    题目: 小O是一个热爱短代码的选手.在缩代码方面,他是一位身经百战的老手.世界各地的OJ上,很多题的最短解答排行榜都有他的身影.这令他感到十分愉悦. 最近,他突然发现,很多时候自己的程序明明看起来比别 ...