《徐徐道来话Java》:泛型的基本概念(1)
来源:互联网 发布:手机淘宝用什么付账 编辑:程序博客网 时间:2024/05/21 06:56
《徐徐道来话Java》:泛型的基本概念(1)
泛型是一种编程范式(Programming Paradigm),是为了效率和重用性产生的。由Alexander Stepanov(C++标准库主要设计师)和David Musser(伦斯勒理工学院CS名誉教授)首次提出,自实现始,就成为了ANSI/ISO C++重要标准之一。
Java自1.5版本开始提供泛型,其本质是一个参数化的类型,那么,何谓参数化?
参数是一个外部变量。设想一个方法,其参数的名称和实际的数值是外部传入的,那么,该参数的类型是否也作为一个参数,在运行时决定呢?这就是泛型的作用。参考如下代码:
List<String> list = newArrayList<String>;
list.add(1);
在第2行,会抛出编译期错误。
The method add(int, String) in the type List<String> is not applicable for the arguments (int)
这就是因为,list在声明时定义了String为自己需要的类型,而1是一个整型数。在上面的例子中,以下几种添加方式都是合法的:
list.add("字符串");
list.add(newString);
String str="字符串";
list.add( str);
在J2SE1.5之前的版本中,Java没有办法显式的对容器进行编译期内容限制,在没有注释或者文档说明的情况下,很容易出现运行时错误。下面举一个错误的例子:
ArrayList list = newArrayList;
list.add(0);
list.add(1);
list.add('2');
list.add(3);
//输出list内容
System.out.println(list);
//遍历输出list内容
for(inti = 0, len = list.size; i < len; i++) {
Integer object = (Integer) list.get(i);
System.out.println(object);
}
输出结果如下所示:
[0, 1, 2, 3]
0
1
Exception in thread "main" java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Integer
at capter3.generic.Generic3_1.test2(Generic3_1.java:28)
at capter3.generic.Generic3_1.main(Generic3_1.java:17)
可以看到,直接输出list的时候,int类型的1和char类型的2是看不出区别的,假设忽略了这点,直接转为Integer来使用的时候,就抛出了强制转化异常。
除了会造成异常外,还可以思考一个问题,如果没有泛型,那么list.get(int)方法返回的始终是个Object,那么要如何在运行时之外确定它的类型呢?
综上,已经证明了泛型存在的必要性,它提供了以下能力:
1、避免代码中的强制类型转换;
2、限定类型,在编译时提供一个额外的类型检查,避免错误的值被存入容器;
3、实现一些特别编程技巧。比如:提供一个方法用于拷贝对象,在不提供额外方法参数的情况下,使返回值类型和方法参数类型保持一致。
1.1.1 泛型的分类
根据泛型使用方式的不同,可分为泛型接口、泛型类和泛型方法。它们的定义如下:
1、泛型接口:在接口定义的接口名后加上<泛型参数名>,就定义了一个泛型接口,该泛型参数名的作用域存在于接口定义和整个接口主体之内;
2、泛型类:在类定义的类名后加上<泛型参数名>,就定义了一个泛型类,该泛型参数名的作用域存在于类定义和整个类主体之内;
3、方法类:在方法的返回值之前加上<泛型参数名>,就定义了一个泛型方法,该泛型参数名的作用域包括方法返回值,方法参数,方法异常,以及整个方法主体。
下面通过一个例子来分别介绍这几种泛型的定义方法,示例代码如下:
/**
* 在普通的接口后加上<泛型参数名>即可以定义泛型接口
*/
interfaceGenericInterface<T> {
* 在类定义后加上<泛型参数名>即可定义一个泛型类,注意后面这个GenericInterface<T>,这里是使用类的泛型参数,而非定义。
*/
classGenericClass<T>implementsGenericInterface<T>{
/**
* 在返回值前定义了泛型参数的方法,就是泛型方法。
*/
public<K, EextendsException> K genericMethod(K param)throwsE {
java.util.List<K> list = newArrayList<K>;
K k = null;
returnnull;
在上例中,class GenericClass<T> implements GenericInterface<T>中有两个地方使用了<T>,它们是同一个概念吗?为了回答这个问题,下面给出几个基本概念,通过对这些基本概念的掌握,将可以解决大部分类似的泛型问题。
a、类(接口)的泛型定义位置紧接在类(接口)定义之后,可以替代该类(接口)定义内部的任意类型。在该类(接口)被声明时,确定泛型参数。
b、方法的泛型定义位置在修饰符之后返回值之前,可以替代该方法中使用的任意类型,包括返回值、参数以及局部变量。在该方法被调用时,确定泛型参数,一般来说,是通过方法参数来确定的泛型参数。
c、<>的出现有两种情况,一是定义泛型,二是使用某个类\接口来具象化泛型。
根据上面介绍的几个基本概念,再来分析class GenericClass<T> implemenets GenericInterface<T>这句代码。可知,class GenericClass是类的定义,那么第一个<T>就构成了泛型参数的定义,而接口GenericInterface是定义在别处的,该代码位置是对此接口的引用,所以,第二个<T>则是使用泛型T来规范GenericInterface。
引申:
如果泛型方法是没有形参的,那么是否还有其它方法来指定类型参数?
答案:有方法指定,但是这个语法并不常见,实现代码如下:
GenericClass<String> gc=newGenericClass<String>;
gc.<String>genericMethod(null);
可以看到这里出现一个很特别的代码形式,gc.genericMethod(null)中间多出了一个<String>,这就是为genericMethod方法进行泛型参数定义了。
- 《徐徐道来话Java》:泛型的基本概念(1)
- 利用ClipDrawable实现照片的徐徐展开
- ClipDrawable资源之徐徐展开的风景
- 【6】Java泛型:泛型的基本概念和使用
- Java泛型:泛型的基本概念和使用
- ClipDrawable的使用,图片的徐徐展开效果
- java简单总结1(对象的基本概念)
- java排序(1):基本概念和各种排序的概述
- 童年的飞秋大门已徐徐向我关闭
- Android中图片的裁剪和徐徐展开控件ClipDrawable
- JAVA的一些基本概念(02)
- JMS(Java Message Service)的基本概念
- Java注解(Annotation)的基本概念
- Java(一)程序的基本概念
- java的一些基本概念
- 一些JAVA的基本概念
- java的一些基本概念
- Java程序设计的基本概念
- Fibonacci数列
- 我的第一条博客
- JavaEE中Web服务器、Web容器、Application服务器区别及联系
- 1451
- 1452
- 《徐徐道来话Java》:泛型的基本概念(1)
- MySQL索引学习笔记
- C++多线程初级一:创建进程
- 1459
- 1481
- Redis内存淘汰机制
- Codeforces Round #385 (Div. 1) B. Hongcow's Game(bitmask)
- 1671
- 序列求和