理解Java泛型最简单的方法是把它看成一种便捷语法,能节省你某些Java类型转换(casting)上的操作:
1 List<Apple> box = ...;
2 Apple apple = box.get(0); 上面的代码自身已表达的很清楚:box是一个装有Apple对象的List。get方法返回一个Apple对象实例,这个过程不需要进行类型转换。没有泛型,上面的代码需要写成这样:
1 List box = ...;
2 Apple apple = (Apple) box.get(0); 很明显,泛型的主要好处就是让编译器保留参数的类型信息,执行类型检查,执行类型转换操作:编译器保证了这些类型转换的绝对无误。 相对于依赖程序员来记住对象类型、执行类型转换——这会导致程序运行时的失败,很难调试和解决,而编译器能够帮助程序员在编译时强制进行大量的类型检查,发现其中的错误。 泛型的构成 由泛型的构成引出了一个类型变量的概念。根据Java语言规范,类型变量是一种没有限制的标志符,产生于以下几种情况: 泛型类声明
泛型接口声明
泛型方法声明
泛型构造器(constructor)声明 泛型类和接口 如果一个类或接口上有一个或多个类型变量,那它就是泛型。类型变量由尖括号界定,放在类或接口名的后面:
1 public interface List<T> extends Collection<T> {
2 ...
3 } 简单的说,类型变量扮演的角色就如同一个参数,它提供给编译器用来类型检查的信息。 Java类库里的很多类,例如整个Collection框架都做了泛型化的修改。例如,我们在上面的第一段代码里用到的List接口就是一个泛型类。在那段代码里,box是一个List<Apple>对象,它是一个带有一个Apple类型变量的List接口的类实现的实例。编译器使用这个类型变量参数在get方法被调用、返回一个Apple对象时自动对其进行类型转换。 实际上,这新出现的泛型标记,或者说这个List接口里的get方法是这样的:
1 T get(int index); get方法实际返回的是一个类型为T的对象,T是在List<T>声明中的类型变量。 泛型方法和构造器(Constructor) 非常的相似,如果方法和构造器上声明了一个或多个类型变量,它们也可以泛型化。
1 public static <t> T getFirst(List<T> list) 这个方法将会接受一个List<T>类型的参数,返回一个T类型的对象。
例子 你既可以使用Java类库里提供的泛型类,也可以使用自己的泛型类。 类型安全的写入数据… 下面的这段代码是个例子,我们创建了一个List<String>实例,然后装入一些数据:
1 List<String> str = new ArrayList<String>();
2 str.add("Hello ");
3 str.add("World."); 如果我们试图在List<String>装入另外一种对象,编译器就会提示错误:
1 str.add(1); // 不能编译 类型安全的读取数据… 当我们在使用List<String>对象时,它总能保证我们得到的是一个String对象:
1 String myString = str.get(0); 遍历 类库中的很多类,诸如Iterator<T>,功能都有所增强,被泛型化。List<T>接口里的iterator()方法现在返回的是Iterator<T>,由它的T next()方法返回的对象不需要再进行类型转换,你直接得到正确的类型。
1 for (Iterator<String> iter = str.iterator(); iter.hasNext();) {
2 String s = iter.next();
3 System.out.print(s);
4 } 使用foreach “for each”语法同样受益于泛型。前面的代码可以写出这样:
1 for (String s: str) {
2 System.out.print(s);
3 } 这样既容易阅读也容易维护。 自动封装(Autoboxing)和自动拆封(Autounboxing) 在使用Java泛型时,autoboxing/autounboxing这两个特征会被自动的用到,就像下面的这段代码:
1 List<Integer> ints = new ArrayList<Integer>();
2 ints.add(0);
3 ints.add(1);
4
5 int sum = 0;
6 for (int i : ints) {
7 sum += i;
8 } 然而,你要明白的一点是,封装和解封会带来性能上的损失,所有,通用要谨慎的使用。 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。 在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。 泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。 泛型在使用中还有一些规则和限制: 1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。 2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。 3、泛型的类型参数可以有多个。 4、泛型的参数类型可以使用extends语句,例如。习惯上成为“有界类型”。 5、泛型的参数类型还可以是通配符类型。例如Class classType = Class.forName(java.lang.String); 泛型还有接口、方法等等,内容很多,需要花费一番功夫才能理解掌握并熟练应用。在此给出我曾经了解泛型时候写出的两个例子(根据看的印象写的),实现同样的功能,一个使用了泛型,一个没有使用,通过对比,可以很快学会泛型的应用,学会这个基本上学会了泛型70%的内容。 例子一:使用了泛型
public class Gen﹤T﹥ {
 private T ob; //定义泛型成员变量  public Gen(T ob) {
this.ob = ob;
 }  public T getOb() {
return ob;
 }  public void setOb(T ob) {
this.ob = ob;
 }  public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
 }
} public class GenDemo {
 public static void main(String[] args){
 //定义泛型类Gen的一个Integer版本
 Gen﹤Integer﹥ intOb=new Gen﹤Integer﹥(88);
 intOb.showTyep();
 int i= intOb.getOb();
 System.out.println("value= " + i);  System.out.println("----------------------------------");  //定义泛型类Gen的一个String版本
 Gen﹤String﹥ strOb=new Gen﹤String﹥("Hello Gen!");
 strOb.showTyep();
 String s=strOb.getOb();
 System.out.println("value= " + s);
} 例子二:没有使用泛型
public class Gen2 {
 private Object ob; //定义一个通用类型成员  public Gen2(Object ob) {
this.ob = ob;
 }  public Object getOb() {
return ob;
 }  public void setOb(Object ob) {
this.ob = ob;
 }  public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
 }
} public class GenDemo2 {
 public static void main(String[] args) {
//定义类Gen2的一个Integer版本
Gen2 intOb = new Gen2(new Integer(88));
intOb.showTyep();
int i = (Integer) intOb.getOb();
System.out.println("value= " + i); System.out.println("----------------------------------"); //定义类Gen2的一个String版本
Gen2 strOb = new Gen2("Hello Gen!");
strOb.showTyep();
String s = (String) strOb.getOb();
System.out.println("value= " + s);
 }
} 运行结果: 两个例子运行Demo结果是相同的,控制台输出结果如下: T的实际类型是:
java.lang.Integer
value= 88
----------------------------------
T的实际类型是: java.lang.String
value= Hello Gen! Process finished with exit code 0 看明白这个,以后基本的泛型应用和代码阅读就不成问题了。

JAVA泛型解释的更多相关文章

  1. Java:泛型基础

    泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...

  2. java泛型基础

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

  3. 浅谈Java泛型之<? extends T>和<? super T>的区别

    关于Java泛型,这里我不想总结它是什么,这个百度一下一大堆解释,各种java的书籍中也有明确的定义,只要稍微看一下就能很快清楚.从泛型的英文名字Generic type也能看出,Generic普通. ...

  4. Java 泛型,了解这些就够用了。

    此文目录: Java泛型是什么? 通常的泛型的写法示例 类型擦除 为什么要使用Java泛型 通过示例了解PECS原则 一.Java泛型是什么? 官方定义 泛型是Java SE 1.5的新特性,泛型的本 ...

  5. Java泛型总结

    1. 什么是泛型?泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型的 ...

  6. java泛型的讲解

    java泛型 什么是泛型? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指 ...

  7. Java泛型:类型擦除

    类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...

  8. java泛型 8 泛型的内部原理:类型擦除以及类型擦除带来的问题

    参考:java核心技术 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首 ...

  9. java 泛型基础问题汇总

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

随机推荐

  1. Linux学习——环境变量设置

    一般来说,配置交叉编译工具链的时候需要指定编译工具的路径,此时就需要设置环境变量.例如我的mips-linux-gcc编译器在“/opt/au1200_rm/build_tools/bin”目录下,b ...

  2. github 使用方法总结 还有一部分不太懂

    1  github在新的目录下添加新的文件 git init //在相应的目录下添加 git add //添加目录 git commit -m "first commit" git ...

  3. IO定时器

    IoInitializeTimer 初始化定时器 IoStartTime 开启定时器 IoStopTimer 停止定时器 回调函数 VOID IoTimer( __in struct DEVICE_O ...

  4. nhibernate 3.3 linq扩展

    nhibernate的sqlserver linq 全文检索搞了半天 方法一 ,扩展LinqToHqlGeneriatorsRegistry http://www.cnblogs.com/xiarug ...

  5. d3可视化实战01:理解SVG元素特性

    一. SVG简介 ————————————————————————————————————————————————————————————————— SVG是一种和图像分辨率无关的矢量图形格式,它使用 ...

  6. TimeZone 时区 (JS .NET JSON MYSQL)

    来源参考 : http://www.cnblogs.com/qiuyi21/archive/2008/03/04/1089456.html 来源参考 : http://walkingice.blogs ...

  7. Android 使用Application总结

    Application 配置全局Context 第一步.写一个全局的单例模式的MyApplication继承自Application 覆盖onCreate ,在这个方法里面实例化Application ...

  8. N次剩余

    $$求解x^n\equiv a(\%P),其中P是质数,0\leq x<P$$ 设$g$是$P$的原根 那么$g^0,g^1,...,g^{P-2}$和$1,2,...,P-1$是一一对应的. ...

  9. [LeetCode] 57. Insert Interval 解决思路

    Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessa ...

  10. hdu-1800

    思路: 这题被坑的不轻. 首先花了一段时间想明白了思路是要找出现次数最多数字,以为这题就这样解决了,结果发现每个数字的最大长度是30,long long都装不下,因此就要用字符串来保存处理.然后在in ...