`
Tiwen
  • 浏览: 84628 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JAVA1.5范型

阅读更多
本文将介绍J2SE 5.0中三个比较重要的特性: 枚举类型, 注释类型, 范型, 并在此基础上介绍在如何在Eclipse 3.1开发环境中开发枚举类型, 注释类型和范型应用。

J2SE 5.0 (Tiger)的发布是Java语言发展史上的一个重要的里程碑, 是迄今为止在 Java 编程方面所取得的最大进步。

J2SE 5.0提供了很多令人激动的特性。这些特性包括范型(generics)的支持, 枚举类型(enumeration)的支持, 元数据(metadata)的支持, 自动拆箱(unboxing)/装箱(autoboxing), 可变个数参数(varargs), 静态导入(static imports), 以及新的线程架构(Thread framework)。

随着J2SE 5.0的推出, 越来越多的集成开发环境(IDE)支持J2SE 5.0的开发。 著名的开源Java IDE Eclipse从3.1M4开始支持J2SE 5.0的开发, 目前最新的版本是3.1RC4。

本系列将介绍J2SE 5.0中三个比较重要的特性: 枚举类型, 注释类型, 范型, 并在此基础上介绍在如何在Eclipse 3.1开发环境中开发枚举类型, 注释类型和范型应用。本文将介绍范型。

3. 范型

3.1范型(Generics)简介
J2SE 5.0中的最显著的变化之一是添加对泛型类型的支持. 在J2SE 1.4 以及之前的版本中, Java程序并不是类型安全的. 例如, Collection framework中定义的List, Map等容器类的元素都是Object类型, 即这个类包含的元素是Object对象. 使用这种方式实现的列表, 可以用来操作整数, 实数, 字符串或者任何对象类型. 例如

清单3.1.1 类型不安全的代码示例
List stringList = new ArrayList();stringList.add("abcde");String str = (String)stringList.get(0);

这种方法实现的列表需要使用强制类型转换(又称显示造型), 因此不是类型安全的. 在上面这段代码种, 虽然变量名为stringList, 但是我们仍然可以把一个整型对象添加到这个队列中, 例如,

清单3.1.2 类型不安全的代码示例
stringList.add(new Integer(5));

在这种情况下, 从字符列表中获取对象时, 强制类型转换就会导致运行时异常.

清单3.1.3 类型不安全的代码示例
String str = (String)stringList.get(1); //runtime exception

范型是Java迈向类型安全的一个重要步骤, 使用范型可以构造出类型安全的代码.

3.2声明范型
所谓范型是指类型参数化(parameterized types). Java是一种强类型的语言, 在J2SE 1.4以及以前的版本中, 我们在定义一个Java类, 接口或者方法的时候, 必须指定变量的类型. 在声明范型类、接口或者函数时, 定义变量的时候不指定某些变量的具体类型, 而是用一个类型参数代替. 在使用这个类, 接口, 或者方法的时候, 这个类型参数由一个具体类型所代替.

3.2.1 范型类

下面的例子中介绍了如何创建一个最简单范型类

清单3.2.1, 最简单的范型类
public class GenSample<T> {}

类名后面带有<T>表明了这个类是范型类, 其中T被成为类型参数(type parameter), 在使用范型的时候, 类型参数可以被替换为任何的类类型, 但是不能是原始类型(primitive type), 例如int, double.

下面通过一个列表的例子来具体说明如果声明范型类和类型参数的用法.

清单3.2.2, 范型列表
public class GenList <T>{	private T[] elements;	private int size = 0;	private int length = 0;	public GenList(int size) {		elements = (T[])new Object[size];		this.size = size;	}	public T get(int i) {		if (i < length) {			return elements[i];		}		return null;	}		public void add(T e) {		if (length < size - 1)			elements[length++] = e;	}}

在列表的例子中, 类型参数T被用来表示列表中的元素的类型, 即, 这个列表中的元素是T类型的.

在使用这个列表时, 这个类型参数T会被具体的类型所替代.

注意, 由于T时类型参数不是具体的类, 所以不能使用new操作符创建T的对象,例如new T(), 或者, new T[10].

3.2.2 范型接口

在J2SE 5.0中, 不仅仅可以声明范型类, 也可以声明范型接口, 声明范型接口和声明范型类的语法类似, 也是在接口命称后面加上<T>. 例如,

清单3.2.3, 范型接口
public interface GenInterface<T> {    void func(T t);}

3.2.3声明多个类型参数的范型类或者接口

在声明范型类的时候, 可是使用多个类型参数. 多个类型参数之间用逗号分开, 例如,

清单3.2.4, 多个类型参数的范型类
public class GenMap<T, V> {}

Eclipse 3.1的类创建向导支持创建范型类, 如下图所示,

图3.2.1 使用类向导创建范型类
图3.2.1 使用类向导创建范型类

使用Eclipse接口向导创建范型接口

图3.2.2 使用接口向导创建范型接口
图3.2.2 使用接口向导创建范型接口

3.2.4范型方法

类型参数(type parameter)不仅仅可以用来声明范型类或者范型接口, 也可以用来声明范型方法, 而且这种声明的范型方法可以用在非范型类中, 声明范型方法的一般格式是

清单3.2.5 范型方法的一般形式
<type-list> return-type method-name(parameter-list) {}
清单3.2.6 范型方法示例
public <T> String getString(T obj) {	return obj.toString();}

3.2.5 受限范型

受限范型是指类型参数的取值范围是受到限制的. extends关键字不仅仅可以用来声明类的继承关系, 也可以用来声明类型参数(type parameter)的受限关系.例如, 我们只需要一个存放数字的列表, 包括整数(Long, Integer, Short), 实数(Double, Float), 不能用来存放其他类型, 例如字符串(String), 也就是说, 要把类型参数T的取值范型限制在Number极其子类中.在这种情况下, 我们就可以使用extends关键字把类型参数(type parameter)限制为数字,

清单3.2.7 受限范型示例
public class Limited<T extends Number> {	public static void main(String[] args) {		Limited<Integer> number;   //正确		Limited<String> str;       //编译错误	}}

在Eclipse 3.1中, 上例中的编译错误信息如下图所示

图3.2.3 由于受限范型导致的编译错误
图3.2.3 由于受限范型导致的编译错误

3.3 在程序中使用范型
3.3.1在程序中使用范型类

在创建范型类的对象的时候, 和创建普通对象基本类似, 必须提供具体的类类型来替代类型参数T (J2SE 5.0目前不支持原始类型作为类型参数(type parameter)).

清单3.3.1, 使用范型类
//如果需要整型的列表GenList<Integer> integerList = new GenList<Integer>();//如果需要字符型的列表GenList<String> strList = new GenList<String>();//不能使用原始类型GenList<int> nList = new GenList<int>();  //编译错误

3.3.2 使用范型解决类型安全性问题
使用范型实现的列表是类型安全的, 下列破坏类型安全语句会在编译的时候检查出来。 把鼠标放在错误标记上, Eclipse 3.1中的错误提示就会显示,如下图所示:

图3.3.2 破坏类型安全引起的错误
图3.3.2 破坏类型安全引起的错误

3.3.3 二义性错误

GenMap在声明是使用了2个类型参数T和V, 因此在创建GenMap的对象的时候也需要提供2个具体的类类型来替代这2个类型参数, 例如,

清单9, 多个参数的范型类
GenMap<Integer, String> gm = new GenMap<Integer, String>();GenMap<String, String> gm2 = new GenMap<String, String>();

上例中, T和V虽然看起来是两个不同的类型参数, 但是在使用这个范型类的时候, T和V很有可能被替换成同一种类型. 因此在声明多个类型参数的范型类时, 要注意避免这种二义性错误, 例如,

清单10, 二义性错误
public class GenMap<T, V> {    //编译错误, 二义性错误    public void set(T t){}    public void set(V v){}}

在上面这段代码, 如果T和V被替换成同一种类型, set函数的签名(signature)就是完全一样的, 所以编译器会报告二义性错误. 正确的用法是声明2个不同名的方法, 例如,

清单10, 二义性错误
public class GenMap<T, V> {    public void setKey(T t){}    public void setValue(V v){}}

图3.3.3 二义性错误
图3.3.3 二义性错误

3.3.4 使用通配符

前面我们创建了范型的列表, 如果我需要一个方法来处理范型列表, 例如, 我们希望把列表中的每个元素都打印出来, 但是类型参数(type parameter)只能使用在声明一个范型类的时候, 如果类型参数使用在函数定义里会导致编译错误


public static void print(GenList<T> list){}	//编译错误

在这种情况下, 我们需要用另外一种方法来表示一个范型类, 否则, 就可能需要书写多个print函数


public static void print(GenList<Integer> list){}public static void print(GenList<Double> list){}…public static void print(GenList<String> list){}

J2SE 5.0中提供了范型的通配符"?", "?"可以用来代替任何类型, 例如使用通配符来实现print方法


public static void print(GenList<?> list) {}

3.4. 范型的一些局限型
(1) 类型参数不能实例化, 例如,


T t= new T();   //编译错误

(2) 不能实例化类型参数的数组


T[] ts= new T[10];   //编译错误

(3) 类的静态变量不能声明为类型参数类型


public class GenClass<T> {     private static T t;    //编译错误}

(4) 范型类不能继承自Throwable以及其子类


public GenExpection<T> extends Exception{}    //编译错误

3.5.范型小结
范型是J2SE 5.0所提供的一项强大的功能, 使用范型可以创建类型安全的、可重用的代码, 虽然目前Java的范型还无法和C++的范型相提并论, 但是, 随着Java语言本事的演进, 范型会在Java语言中发挥更大的作用的. 



分享到:
评论

相关推荐

    java1.5范型编程指南

    java1.5范型编程指南.docjava1.5范型编程指南.docjava1.5范型编程指南.docjava1.5范型编程指南.docjava1.5范型编程指南.doc

    jdk1.5中的范型

    JDK1.5 中引入了对 java 语言的多种扩展,泛型(generics)即其中之一。

    java范型视频

    泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是...

    Thinking in java4(中文高清版)-java的'圣经'

    1.8 单根继承结构 1.9 容器 1.9.1 参数化类型(范型) 1.10 对象的创建和生命期 1.11 异常处理:处理错误 1.12 并发编程 1.13 Java与Internet 1.13.1 Web是什么 1.13.2 客户端编程 1.13.3 服务器端编程 1.22 总结 第...

    StudyJava:Java 基础学习(java编程思想和java技术核心卷)

    StudyJavaJava Basics1.java 基础学习2.java变成思想和java核心技术整理3.java8等java新特性学习整理###Java编程思想第1章 对象导论1.1 抽象过程1.2 每个对象都有一个接口1.3 每个对象都提供服务1.4 被隐藏的具体...

    thinking in Java 第四版中文 part1

    1.5 复用具体实现 1.6 继承 1.6.1 “是一个”(is-a)与“像是一个”(is-like-a)关系 1.7 伴随多态的可互换对象 1.8 单根继承结构 1.9 容器 1.9.1 参数化类型(范型) 1.10 对象的创建和生命期 1.11 异常处理:...

    北京达内 core java核心课件(含练习题)

    JAVA_HOME=/opt/jdk1.5 CLASSPATH=. PATH=$PATH:$JAVA_HOME/bin:. 注: “.”代表当前目录 当我们把环境变量都配置好了以后在终端敲入”java -version”命令如果出现 JDK 版本号信息就表示我们环 境...

    google-collections

    google collections使用了范型,所以要求jdk1.5以上。它的作者没有像apache commons collections一样照顾老的jdk版本,一个原因是google的jdk基本都是1.5以上,另一个原因是类型转换实在是太难看了。现在的集合库...

    编程思想下篇

    1.5 复用具体实现 1.6 继承 1.6.1 “是一个”(is-a)与“像是一个”(is-like-a)关系 1.7 伴随多态的可互换对象 1.8 单根继承结构 1.9 容器 1.9.1 参数化类型(范型) 1.10 对象的创建和生命期 1.11 异常处理:...

    google-collections-1.0.rar

    google公共工具类;google collections是google的工程师利用传说中的“20%时间”开发的集合库,它是对java.util的扩展,提供了很多实用的类来简化代码。google collections使用了范型,所以要求jdk1.5以上。

    编程新手真言......

    1.5 分段和分页以及保护模式 30 1.7 操作系统 31 1.6 并发与协程 33 1.6 CPU与异常 33 1.7 所谓堆栈 34 1.8 真正的保护模式 36 1.9 异常与流转 38 1.10 最小,最完美的系统 39 1.11 操作系统与语言的关系 41 1.12 ...

Global site tag (gtag.js) - Google Analytics