`

java泛型示例

阅读更多
使用泛型机制编写的程序代码要比那些杂乱地使用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泛型接口的相关知识点。 1. **泛型接口的定义** 泛型接口的定义方式与普通接口类似,只是在接口名之后添加了尖括号`&lt;T&gt;`,其中`T`是一个类型参数,代表某种未知的数据类型。例如: ```java...

    java 泛型方法使用示例

    下面我们将深入探讨Java泛型方法的概念、语法以及使用示例。 **一、泛型方法概念** 泛型方法是一种具有类型参数的方法,这些类型参数可以在方法声明时指定,并在方法体内部使用。与类的泛型类似,它们提供了编译时...

    java 泛型类的类型识别示例

    在Java编程语言中,泛型(Generics)是一种强大的特性,它允许我们在编写代码时指定容器(如集合)可以存储的数据类型。这提高了代码的安全性和效率...通过学习和理解这些示例,你可以更好地掌握Java泛型类的类型识别。

    Java泛型的用法及T.class的获取过程解析

    Java泛型的用法及T.class的获取过程解析 Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析...

    Java泛型使用详细分析.pdf

    Java 泛型使用详细分析 Java 泛型是 Java 语言中的一种类型系统特性,允许开发者在编译期检查类型安全,以避免在运行时出现类型相关的错误。在本文中,我们将详细介绍 Java 泛型的使用方法和实现原理。 一、泛型的...

    面试必须资料java泛型攻略、

    #### 一、什么是Java泛型? Java泛型(Generics)是一种在编译时确保类型安全的机制,它允许程序员编写类型安全的通用类或方法,而无需进行显式的类型转换。在Java 1.5引入泛型之前,集合类(如`ArrayList`)只能...

    java泛型Demo

    Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入。泛型的主要目的是提供类型安全,帮助程序员在编译时发现可能的类型错误,同时也提供了更好的代码重用。在这个"java泛型Demo"中,我们...

    java泛型深入.pdf

    Java泛型是Java语言中用于处理类型安全的一种机制,它允许在编译期间提供类型检查,并在运行时消除了类型转换。Java泛型深入的内容涵盖泛型的基本概念、泛型类、接口、方法以及泛型的使用限制和高级特性。 首先,...

    java 继承泛型类示例

    了解这些概念后,我们可以看到`GenericClass.java`文件可能包含了关于如何创建和使用继承泛型类的实际代码示例。而`Java.jpg`可能是用于辅助解释的图像,比如类结构图或代码截图。在实际学习过程中,结合代码和图像...

    java 泛型的使用 详细讲解

    ### Java泛型的使用详细讲解 #### 一、引言 在Java开发中,泛型是一种重要的语言特性,它能够帮助开发者在不增加代码量的情况下处理多种数据类型,同时还能保持代码的清晰度和可读性。本文将详细介绍Java泛型的...

    java泛型初探

    Java泛型是Java编程语言中的一个...在“java泛型的高级用法demo”中,你可以期待更深入的示例,如限制类型参数、创建多级泛型、使用泛型接口等复杂应用场景。实践这些示例将有助于进一步理解并熟练掌握Java泛型的精髓。

    JVM如何理解Java泛型类.doc

    ### JVM如何理解Java泛型类 #### 一、引言 在Java中,泛型是一种强大的功能,它允许程序员编写灵活且类型安全的代码。然而,对于Java虚拟机(JVM)来说,它实际上并不理解泛型的概念。所有的泛型信息在编译阶段就被...

    全面总结Java泛型--实例

    ### 泛型示例解析 #### 示例一:泛型类 ```java class Point&lt;T&gt; { private T var; public T getVar() { return var; } public void setVar(T var) { this.var = var; } } ``` 这里定义了一个泛型类`...

    java泛型例子

    Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入,极大地增强了类型安全性和代码可读性。泛型允许我们在编写代码时指定容器(如集合)可以存储的数据类型,从而在编译阶段就能捕获类型...

    JAVA泛型教程(帮你解决学习泛型的苦恼)

    Java泛型是Java语言的一个重要特性,它允许在类、接口和方法中声明类型参数,从而提高了代码的复用性和安全性。这个特性自Java 5引入以来,极大地改善了Java的类型系统,降低了类型转换异常的风险。 1. **使用泛型...

    Java泛型实例

    Java泛型是Java编程语言中的一个重要特性,它在2004年随着Java SE 5.0的发布而引入。这个特性允许程序员在定义类、接口和方法时声明类型参数,从而增强了代码的类型安全性和重用性。通过使用泛型,我们可以编写更加...

    Java泛型与容器详细笔记.pdf (带书签)

    Java泛型与容器详细笔记涉及到Java编程语言中的两个重要概念:泛型(Generics)和容器(Containers)。容器主要包括Java集合框架中的各类集合类,如List、Set、Map等,它们用于存储和操作数据。泛型则提供了一种类型...

Global site tag (gtag.js) - Google Analytics