java基础-泛型1
浏览以下内容前,请点击并阅读 声明
泛型的使用能使类型名称作为类或者接口定义中的参数,就像一般的参数一样,使得定义的类型通用性更强。
泛型的优势:
- 编译具有严格的类型检查
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的更多相关文章
- 一天一个Java基础——泛型
这学期的新课——设计模式,由我仰慕已久的老师传授,可惜思维过快,第一节就被老师挑中上去敲代码,自此在心里烙下了阴影,都是Java基础欠下的债 这学期的新课——算法设计与分析,虽老师不爱与同学互动式的讲 ...
- Java 基础 -- 泛型、集合、IO、反射
package com.java.map.test; import java.util.ArrayList; import java.util.Collection; import java.util ...
- java基础-泛型举例详解
泛型 泛型是JDK5.0增加的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数.这种类型参数可以在类.接口.和方法的创建中,分别被称为泛型类.泛型接口.泛型方法. 一.认识泛型 在没 ...
- Java基础 - 泛型详解
2022-03-24 09:55:06 @GhostFace 泛型 什么是泛型? 来自博客 Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了&quo ...
- java基础-泛型3
浏览以下内容前,请点击并阅读 声明 8 类型擦除 为实现泛型,java编译器进行如下操作进行类型擦除: 如果类型参数有限制则替换为限制的类型,如果没有则替换为Object类,变成普通的类,接口和方法. ...
- java基础 泛型
泛型的存在,是为了使用不确定的类型. 为什么有泛型? 1. 为了提高安全 2. 提高代码的重用率 (自动 装箱,拆箱功能) 一切好处看代码: package test1; import java.la ...
- java基础-泛型2
浏览以下内容前,请点击并阅读 声明 6 类型推测 java编译器能够检查所有的方法调用和对应的声明来决定类型的实参,即类型推测,类型的推测算法推测满足所有参数的最具体类型,如下例所示: //泛型方法的 ...
- Java基础---泛型、集合框架工具类:collections和Arrays
第一讲 泛型(Generic) 一.概述 1.JDK1.5版本以后出现的新特性.用于解决安全问题,是一个类型安全机制. 2.JDK1.5的集合类希望在定义集合时,明确表明你要向集合中装入那种类 ...
- Java基础——泛型
一.定义 泛型(generic)是指参数化类型的能力.可以定义带泛型类型的类或方法,随后编译器会用具体的类型来替换它(泛型实例化).使用泛型的主要优点是能够在编译时,而不是在运行时检测出错误.它是jd ...
随机推荐
- C#------连接SQLServer和MySQL字符串
<connectionStrings> <add name="ConnectionStrings" connectionString="Data Sou ...
- gis数据格式转换(数据导入)ConvertFeaCls
本文主要对数据导入等里 常用的不同格式数据创建.转换等 进行代码示例.主要用到IFeatureDataConverter.ConvertFeatureClass方法. 代码如下,难度不大,只是个技巧问 ...
- Android检测网络是否正常代码!
在Android开发中,如果该应用程序需要连接网络请求,那么最好我们先做一个检测网络是否在线的判断,否则程序容易出现卡死或FC等Bug,应该判断如果手机离线则弹出提示让用户检查网络,如果正常则继续执行 ...
- PHP连接mysql数据库,并将取出的数据以json的格式输出
<?php error_reporting(E_ALL || ~E_NOTICE); header("Access-Control-Allow-Origin:*");//此处 ...
- C和指针 第十章 结构和联合 (一)
结构体: 聚合数据类型是指,能够同时存储超过一个的单独数据,C语言中有两个聚合数据类型,数组和结构体.数组中储存的类型必须相同,元素通过下标和指针引用来访问的. 结构体也是一些值的集合,但是结构体中每 ...
- (转)android自定义组合控件
原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linea ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- 检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(转)
我们将ASP.NET程序从IIS6移植到IIS7,可能运行提示以下错误: HTTP 错误 500.23 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ASP.N ...
- JS 删除对象属性
updateNode: function(data) { if(data) { this.root[data.id] = data; } }, removeNodes: function(idsArr ...
- phpcms
phpcms 织梦 帝国cms