使用泛型机制编写的程序代码要比那些杂乱地使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。
泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。
一个泛型类就是具有一个或多个类型变量的类。
如下面的Pair例子,就是一个泛型类
package ch13genic;
public class Pair<T> {
private T first;
private T second;
public Pair(){
first = null;
second = null;
}
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
}
该类引人了类型变量T,用尖括号<>扩起,放在类名的后面,泛型类可以有多个类型变量,例如public class Pair<T,U>{....},
用具体的类型替换类型变量就可以实例化泛型类型:如Pair<String>,泛型类可以看做普通类的工厂。
package ch13genic;
public class PairTest1
{
public static void main(String[] args)
{
String[] words = { "Mary", "had", "a", "little", "lamb" };
Pair<String> mm = ArrayAlg.minmax(words);
System.out.println("min = " + mm.getFirst());
System.out.println("max = " + mm.getSecond());
String midStr = ArrayAlg.<String>getMiddle(words); //调用泛型方法,也可以省略<String>,因为编译器根据words匹配T[] a,判断出T一定是String。
System.out.println(midStr);
// int[] a = {1,23,45,56,3};
// int aMid = ArrayAlg.getMiddle(a); 编译出错,为什么?猜测:因为T是一个类型变量,代表的是一个类,而int只是基本类型
// Integer[] a ={1,23,45,56,3};
// int aMid = ArrayAlg.getMiddle(a);
// System.out.println(aMid);
}
}
class ArrayAlg
{
public static Pair<String> minmax(String[] a)
{
if (a == null || a.length == 0) return null;
String min = a[0];
String max = a[0];
for (int i = 1; i < a.length; i++)
{
if (min.compareTo(a[i]) > 0) min = a[i];
if (max.compareTo(a[i]) < 0) max = a[i];
}
return new Pair<String>(min, max);
}
public static <T> T getMiddle(T[] a){
//示意:带有类型参数的方法。由于这个类不是在泛型类中定义的,要用<T>引人类型变量,它放在修饰符和返回值之间
return a[a.length/2];
}
}
类型变量的限定
有时类或方法需要对类型变量加以约束。下面是一个典型的例子
class ArrayAlg{
public static <T> T min(T[] a) {
if (a == null || a.length == 0)
return null;
T min = a[0];
for (int i = 0; i < a.length; i++) {
if (min.compareTo(a[i]) < 0)
min = a[i];
}
return min;
}
}
这里有一个问题,变量min的类型为T,意味着它可以是任何一个类的对象。怎么才能确信T所属的类有compareTo方法呢?
解决这个问题的答案是将T限制为实现了Comparable接口的类,如
public static <T extends Comparable> T min(T[] a){
}
实际上,Comparable本身就是一个泛型接口:public interface Comparable<T>,唯一的方法:compareTo(T o) 如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
可能有些奇怪,为什么使用关键字extends而不是implements?比较,Comparable是一个接口啊,下面的符号:
<T extends BoundingType>
表示T应该是绑定类型的子类型,T和绑定类型可以是类,也可以是接口。
一个类型变量可以有多个限定,例如
T extends Comparable & Serializable
限定类型用 & 分隔,这是因为用逗号分隔类型变量
package ch13genic;
import java.util.*;
public class PairTest2
{
public static void main(String[] args)
{
GregorianCalendar[] birthdays =
{
new GregorianCalendar(1906, Calendar.DECEMBER, 9), // G. Hopper
new GregorianCalendar(1815, Calendar.DECEMBER, 10), // A. Lovelace
new GregorianCalendar(1903, Calendar.DECEMBER, 3), // J. von Neumann
new GregorianCalendar(1910, Calendar.JUNE, 22), // K. Zuse
};
Pair<GregorianCalendar> mm = ArrayAlg.minmax(birthdays);
System.out.println("min = " + mm.getFirst().getTime());
System.out.println("max = " + mm.getSecond().getTime());
}
}
class ArrayAlg
{
/**
Gets the minimum and maximum of an array of objects of type T.
@param a an array of objects of type T
@return a pair with the min and max value, or null if a is
null or empty
*/
public static <T extends Comparable> Pair<T> minmax(T[] a)
{
if (a == null || a.length == 0) return null;
T min = a[0];
T max = a[0];
for (int i = 1; i < a.length; i++)
{
if (min.compareTo(a[i]) > 0) min = a[i];
if (max.compareTo(a[i]) < 0) max = a[i];
}
return new Pair<T>(min, max);
}
}
泛型的约束和限制:
不能用类型参数替换基本类型,因此没有Pair<double>,只有Pair<Double>.虚拟机没有泛型类型对象,所有对象都是
普通对象。所有的类型查询只产生原始类型,如List而非List<String>等。getClass总是返回原始类型。
if(a instanceof Pair<String>)等价if(a instanceof Pair)
Pair<String> p = new Pair("first", "second");
Pair<Integer> p1 = new Pair();
System.out.println(p.getClass().getName());// ch13genic.Pair
System.out.println(p1.getClass().getName()); // ch13genic.Pair
List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass().getName());// java.util.ArrayList
System.out.println(l2.getClass().getName()); // java.util.ArrayList
泛型类不能扩展Throwable。如public class Problem<T> extends Exception {
。。。
} //error The generic class Problem<T> may not subclass java.lang.Throwable
不能在catch子句中使用类型变量。如下面的方法将不能编译:
try{
//do work
}catch(T e){ //error:Cannot use the type parameter T in a catch block
// logger.info("");
}
}
但是,在异常声明中可以使用类型变量。下面这个方法是合法的:
public static <T extends Throwable> void doWork(T t) throws T{//ok
try{
//do work
}catch(Throwable e){ //error:Cannot use the type parameter T in a catch block
t.initCause(e);
throw t;
}
}
不能申明参数化类型的数组,如:
Pair<String>[] table = new Pair<String>(10); //error
如果需要收集参数化类型对象,直接使用ArrayList:ArrayList<Pair<String>>最安全且有效。
不能实例化泛型类型,如:
public Pair(T first, T second) { //error
this.first = new T();
this.second = new T();
}
不能建立一个泛型数组,如:
T[] t = new T[20]; //error
不能在静态域或方法中引用类型变量,如:
public class Singleton<T> {
private static T singleInstance; //error:Cannot make a static reference to the non-static type T
public static T getSingleInstance(){//error
if(singleInstance==null){
// construct new instance of T
}
return singleInstance;
}
}
一个类和一个子类,Pair<Employee>与Pair<Manager>,前者是后者的子类吗?不是。无论S、T有何关系,Pair<S>和Pair<T>没有什么联系。
分享到:
相关推荐
java 泛型接口示例 java 泛型接口示例 java 泛型接口示例
java 泛型方法使用示例 java 泛型方法使用示例 java 泛型方法使用示例
java 泛型类的类型识别示例 java 泛型类的类型识别示例 java 泛型类的类型识别示例
主要介绍了多个java泛型示例,需要的朋友可以参考下
java 继承泛型类示例 java 继承泛型类示例 java 继承泛型类示例
主要介绍了Java泛型的用法及T.class的获取过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
java 继承非泛型类示例 java 继承非泛型类示例 java 继承非泛型类示例
Java 泛型教程
winform 泛型示例源码! 很值得下载看看!资源免费,大家分享!!
这段代码实现了一个简单的银行账户类BankAccount,其中使用了Java泛型来支持不同类型的账户。...这个简单的示例代码展示了如何使用Java泛型来实现一个通用的银行账户类,方便了不同类型的账户管理。
环境:Windows XP Professional、JDK 1.6、Ant 1.7 说明:Java泛型的动机是为解决类型转换在编译时不报错的问题。另外由于“范型编程”(Generic Programming)的推广,于是2004年JDK 5.0引用范型标准。本例子说明...
主要介绍了Java泛型定义与用法,结合实例形式分析了java泛型的功能、定义、应用场景及相关使用注意事项,需要的朋友可以参考下
主要介绍了Java泛型的继承和实现操作,结合实例形式分析了java泛型类的继承以及泛型接口的实现相关操作技巧,需要的朋友可以参考下
主要介绍了Java泛型和Class类用法,结合实例形式分析了java使用泛型限制class类避免强制类型转换相关操作技巧,需要的朋友可以参考下
Java泛型(Generics)是JDK5开始引入的一个新特性,允许在定义类和接口的时候使用类型参数(Type Parameter)。下面是学习泛型的示例
主要介绍了Java泛型extends关键字设置边界的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
主要介绍了Java泛型变量如何添加约束,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
Java 集合与泛型示例 Github 路径 作者 目录 LICENSE
学习和理解Java泛型的基本概念和语法; 实际项目中需要使用泛型来增加类型安全性和重用性的开发任务。 目标: 本代码资源的目标是帮助读者理解泛型的用法和优势,并通过实际的示例代码加深对泛型的掌握。读者可以...
主要介绍了Java泛型extends及super区别实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下