浏览以下内容前,请点击并阅读 声明

 泛型的使用能使类型名称作为类或者接口定义中的参数,就像一般的参数一样,使得定义的类型通用性更强。

 泛型的优势:

  • 编译具有严格的类型检查

  java编译器对于泛型代码的类型检查更加严格,能够发现普通代码中的一些运行时错误。

  • 消除类型转化  
//如下代码未使用泛型,需要进行类型的转化
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0); //泛型的使用可以不适用类型转化
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0); // no cast
  • 能够使程序员实现通用的算法

  通过使用泛型,使得一类不同的类型能够进行通用的运算。

1 泛型

   泛型是将类型参数化的类或者接口。

1.1 泛型的声明

  一般泛型的声明类似如下:

class name<T1, T2, ..., Tn> { /* ... */ }

  尖括号中的参数就是类型参数,参数由逗号隔开,类型参数可以是任何非基本数据类型的任何类型,泛型的接口声明与上述泛型类类似。

1.2 泛型参数命名

  一般情况下,泛型类型参数的名称是单个大写字母,和变量名称鲜明地区分开来。

  最通用的参数类型参数名称为:

  • E - 元素 (被java集合框架应用)
  • K - 键
  • N - 数字
  • T - 类型
  • V - 值
  • S,U,V 等等 - 第二,第三, 第四类型

  在javaSE API中这些名称被广泛使用

1.3 调用和实例化泛型

  如需引用一个泛型,首先要进行一个泛型的调用,如下所示:

//传入类型参数,如下为String作为类型参数
ArrayList<String> list;

  上述代码可以看做个调用方法类似,不过是以类型为参数,这一过程叫参数化类型,实例化泛型的语法如下:

//一下声明和实例化一步完成
ArrayList<String> list=new ArrayList<String>();

1.4 钻石

  java7以后,只要编译器能够根据代码的上下文判断类型参数,就可以将泛型的构造器的类型实参留空(<>)由于空的尖括号形状就像钻石,所以非正式的成为钻石,如上述代码可以简写为:

//注意构造器内的参数已经省略
ArrayList<String> list=new ArrayList<>();

1.5 参数化类型作为类型参数

  泛型的类型参数也可以是参数话的泛型,如:

//省略构造器类型参数
ArrayList<List<String>> list=new ArrayList<>();

2 原始类型

2.1定义

  原始类型是指没有类型参数的泛型。例如一下声明一个原始类型:

//ArrayList是一个泛型,因此List变量是原始类型
ArrayList list=new ArrayList();

  原始类型的旧的java版本的遗产,因为许多API类如集合类在JDK5之前不是泛型,为了向下兼容,将一个参数化的泛型对象赋值给一个原始类型是允许的:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox; // OK

  不过反过来,将一个原始类型赋值给一个参数化的泛型,编译器将会给出警告:

Box rawBox = new Box();           // rawBox是 Box<T>的原始类型
Box<Integer> intBox = rawBox; // 警告: unchecked conversion

  如果使用原始类型去调用队形的泛型的泛型方法,同样也会得到警告:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8); // warning: unchecked invocation to set(T)

  编译器警告表明原始类型绕过了类型的检查,而将可能出错的风险留到了运行时,所以尽量不要使用原始类型。

2.2 未检查错误信息

  如之前所提到的,当泛型和传统语法混用时,你将会遇到一些如下的警告消息:

    Note: Example.java uses unchecked or unsafe operations.   

    Note: Recompile with -Xlint:unchecked for details.

  “unchecked”(未检查的)这一术语表明编译器没有足够的关于类型信息来执行检查以确保类型的安全,编译器默认警用未检查警告,但是会给出提示,如果想要启用未检查警告,在编译时加入参数 -Xlint:unchecked

  如果想要完全禁用未检查警告,可以编译时加入参数-Xlint:-unchecked(注意与上述参数区别)或者使用注释@SuppressWarnings("unchecked")

3 泛型方法

  泛型方法是指引入自身的参数类型的方法,就像泛型的类型参数一样,不过方法的类型参数的使用范围仅限于方法自身。可以定义静态和非静态的泛型方法,同时也可以定义使用泛型构造器。

  泛型方法的语法含有位于方括号内的类型参数,位于方法返回类型之前,当然,非泛型的类也可以包含泛型方法。

  如下举例说明泛型方法的声明:

public class Util {
//以下方法为泛型方法
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
} public class Pair<K, V> { private K key;
private V value; public Pair(K key, V value) {
this.key = key;
this.value = value;
} public void setKey(K key) { this.key = key; }
public void setValue(V value) { this.value = value; }
public K getKey() { return key; }
public V getValue() { return value; }
}

完整的调用泛型方法的语法为:

//以下语句利用了上述定义的类
Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");
boolean same = Util.<Integer, String>compare(p1, p2);

当然,如果编译其能够推测出类型,可省略泛型方法的类型参数:

Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");
boolean same = Util.compare(p1, p2);

4 限制类型参数范围

  有时候你可能需要限定泛型的类型参数,比如限定某个泛型的类型参数只能为Number或者是其子类或者继承类。

  声明类型参数的限定,就是在参数名称之后跟上extends关键词,然后跟上其上限,如Number,在这里extends通常意义上是指类的extends和接口的implements。,如一下方法的声明:

public <U extends Number> void inspect(U u){
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}

  一个类型参数可以有多重限定,即extends关键词后跟多个上限,用符号&隔开:

class D <T extends A & B & C> { /* ... */ }

5 泛型,继承和子类型

  java中可以将一个类型的对象赋值给另外一个类型的变量,如果两个类型相兼容的话,如可以将Integer类型的对象赋值给类型为Object的变量。在面向对象的术语中,这是一种叫做“是一个”的关系,如Integer类型是一个Object类型,因此允许上述的赋值。方法包括泛型的方法的参数的传递也是如此,如

//如下进行类型参数化的ArrayList类型的元素类型为Number
ArrayList<Number> list=new ArrayLIst<Number>();
//其add方法参数类型也是Number,也可以使用其子类Integer的实例
list.add(new Integer(10));

  但是对于泛型的子类型关系,与普通的类型是有区别的,如下图所示:

箭头表示子类型的关系,如Integer是Number的子类型,而Box<Integer>则不是Box<Number>的子类型,Box<Integer>和Box<Number>的共同的父类型是Object。

  你可以通过继承或者实现一个泛型来成为该泛型一个子类型。类或者接口的类型参数之间的关系是由extends和implements语句决定的。

  比如集合类,ArrayList<E>实现List<E>,List<E>继承Collection<E>所以ArrayList<String>是List<String>的子类型,List<String>是Collection<String>的子类型,只要不变更类型参数,这种继承关系就会保留:

现在自定义一个新的继承List接口的接口:

//注意类型参数的名称
interface PayloadList<E,P> extends List<E> {
void setPayload(int index, P val);
...
}

  类型参数化的类型则由如下关系:

java基础-泛型1的更多相关文章

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

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

  2. Java 基础 -- 泛型、集合、IO、反射

    package com.java.map.test; import java.util.ArrayList; import java.util.Collection; import java.util ...

  3. java基础-泛型举例详解

    泛型 泛型是JDK5.0增加的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数.这种类型参数可以在类.接口.和方法的创建中,分别被称为泛型类.泛型接口.泛型方法. 一.认识泛型 在没 ...

  4. Java基础 - 泛型详解

    2022-03-24 09:55:06 @GhostFace 泛型 什么是泛型? 来自博客 Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了&quo ...

  5. java基础-泛型3

    浏览以下内容前,请点击并阅读 声明 8 类型擦除 为实现泛型,java编译器进行如下操作进行类型擦除: 如果类型参数有限制则替换为限制的类型,如果没有则替换为Object类,变成普通的类,接口和方法. ...

  6. java基础 泛型

    泛型的存在,是为了使用不确定的类型. 为什么有泛型? 1. 为了提高安全 2. 提高代码的重用率 (自动 装箱,拆箱功能) 一切好处看代码: package test1; import java.la ...

  7. java基础-泛型2

    浏览以下内容前,请点击并阅读 声明 6 类型推测 java编译器能够检查所有的方法调用和对应的声明来决定类型的实参,即类型推测,类型的推测算法推测满足所有参数的最具体类型,如下例所示: //泛型方法的 ...

  8. Java基础---泛型、集合框架工具类:collections和Arrays

    第一讲     泛型(Generic) 一.概述 1.JDK1.5版本以后出现的新特性.用于解决安全问题,是一个类型安全机制. 2.JDK1.5的集合类希望在定义集合时,明确表明你要向集合中装入那种类 ...

  9. Java基础——泛型

    一.定义 泛型(generic)是指参数化类型的能力.可以定义带泛型类型的类或方法,随后编译器会用具体的类型来替换它(泛型实例化).使用泛型的主要优点是能够在编译时,而不是在运行时检测出错误.它是jd ...

随机推荐

  1. Linux系统下压缩文件时过滤指定的文件 |Linux系统压缩指定文件代码

    进入要压缩的目录: [root@iZ25c748tjqZ wechat]# cd /alidata1/htdocs/wechat/ 查看目录: [root@iZ25c748tjqZ wechat]# ...

  2. IntelliJ IDEA 15 在线激活地址

    License server,直接输入http://www.iteblog.com/idea/key.php地址即可激活IntelliJ IDEA 15:

  3. windows下pip安装python模块时报错总结

    http://www.cnblogs.com/liaojiafa/p/5100550.html 前言: 这几天把python版本升级后,发现pip安装模块好多都报错(暂不确定是不是因为升级导致的),我 ...

  4. 好用的开源web系统总结

    1.论坛 phpwind 一个用wind框架写的论坛       discuz 社区动力 论坛   2.商城 Ecshop 商城腾讯的开源商城项目 一款B2C独立网店系统,系统是基于PHP语言及MYS ...

  5. cnblog中添加数学公式支持

    在博客中使用数学公式,是一件相对麻烦的事儿,大量的截图和插入图片不仅耗费极大的精力,而且影响写作体验. 虽然对于公式显示已经有多种解决办法,但大多数需要安装插件.而MathML这一雄心勃勃的网页数学语 ...

  6. 快排 快速排序 qsort quicksort C语言

    现在网上搜到的快排和我以前打的不太一样,感觉有点复杂,我用的快排是FreePascal里/demo/text/qsort.pp的风格,感觉特别简洁. #include<stdio.h> # ...

  7. [转]Oracle存在则更新,不存在则插入

    原文:http://hi.baidu.com/mawf2008/item/eec8c7ad1c5be5ae29ce9da6 merge into a using bon (a.a=b.b)when m ...

  8. AndroidStudio使用笔记

    声明: 正式放弃Eclipse,投奔AndoidStudio大军,有些东西要从头摸索,特发此帖记录Android Studio的使用方法.本帖永久更新,不定时记录本人使用过程中的经验积累,给自己留一份 ...

  9. 如何学习JavaScript

    Javascript是我大学里面做网站兴趣,加上进一年维护公司javascript相关的框架. 顺便回顾一下自己学习 javascript 的相关方法和技巧,分享给需要的朋友. 1.base 基础.兼 ...

  10. GDI+ 笔记

    1.GDI+模板 #include<windows.h> #include<GdiPlus.h> #include <time.h> #include <ma ...