泛型机制常用的参数有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. mysql自定义函数语法

    创建函数 DELIMITER $$DROP FUNCTION IF EXISTS `test` $$CREATE FUNCTION `test`(a int ,b int)RETURNS int BE ...

  2. 剑指offer之 整数中1出现的次数

    public class Solution { public int NumberOf1Between1AndN_Solution(int n) { int count=0; for(int i=1; ...

  3. matlat之KDTreeSearcher()函数

    Create Kd-tree nearest neighbor searcher(创建kd-树最近邻搜索器). Description KDTreeSearcher model objects sto ...

  4. RadioButton控件选中、取消

    js: var flag = true; function chkRadio(id) { id.checked = flag; flag = !flag; } aspx.cs: this.rbtKey ...

  5. python习题-判断输入字符串是不是小数类型

    写一个能判断输入的字符串是不是个小数类型的1,判断小数点的个数是否为1 count2,判断是否小数右边是整数 isdigit3,判断小数点左边的1,整数 isdigit ,2如果是负整数,取负号右边, ...

  6. Chrome_01_点击 Google搜索结果在新的页面打开

    方法一:Ctrl + 左键 Chrome浏览器中,通过 Ctrl + 左键 ,是在新标签中打开的,通过 Shift + 左键 ,是在新窗口中打开的. 方法二: 1.登录 Google 2.进入下面的设 ...

  7. 05 - Django应用第二步

    知识点 1) 数据库的配置 涉及到INSTALL_APPS的配置等 初次创建数据的命令 2) 模型的编写 模型的创建方式, 写一个类继承自models.Model 模型的数据类型 外键 自动创建ID列 ...

  8. CCUserDefault 存档

    void HelloWorld::testCCUserDefault() { CCSize size = CCDirector::sharedDirector()->getWinSize(); ...

  9. HDOJ1677(铺砖问题)

    Nested Dolls Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  10. .NET接入微信支付(一)JS API接入 V3

    前段时间刚接完银联支付,完事后又接了微信支付,前段时间一直急着上线,微信的接入一直没有时间处理,今天我们就来整理一下微信支付的接入方法和要点. 配置: 首先呢微信支付需要通过审核,审核啥的准备工作我就 ...