泛型学习笔记

泛型学习

一.Java中引入泛型(Generics)的原因:
1.解决数据类型转换的错误:
  由于在程序中要使用具体的数据类型,因此要对表达式进行向下的类型转换(downCast),
  编译时会通过,但在运行时会发生ClassCastException异常。
  类型转换的缺点:

 1.使java代码变得更加冗长
 2.降低了静态类型检查的价值(因为每个数据类型转换都是一个选择忽略静态类型检查的伪指令)。
二.自定义泛型:
1.定义泛型类:
  //GenericFoo.java
  public class GenericFoo<T>

 { private T foo;
 
  public void setFoo(T foo){
   this.foo = foo;
  }
 
  public T getFoo(){
   return foo;
  }
  }
  使用<T>来声明一个类型持有者(Holder)名称T,用T这个名称作为类型代表来声明成员,参数,或返回值类型。
2.使用自定的泛型:
  //GenericFooDemo.java
  public class GenericFooDemo{
  public static void main(String [] args){
  GenericFoo<Boolean> foo1 = new GenericFoo<Boolean>();
  GenericFoo<Integer> foo2 = new GenericFoo<Integer>();

  foo1.setFoo(new Boolean(true));
  Boolean b = foo1.getFoo();//不需要再转换类型
  System.out.println(b);

  foo2.setFoo(new Integer(10));
  Integer i = foo2.getFoo();//不需要再转换类型
  System.out.println(i);
  }
  }
3.与使用Object声明类型不同的地方:
  使用泛型所定义的类在声明及配置对象时,可以使用<Type>指定类型持有者T真正的类型,就不需要进行类型的强制转换();
  getFoo()设置的参数和返回的德类型,就是声明在<>之间所指定的类型。这样就避免了ClassCastException异常的发生。
4.如在定义泛型类时,不指定类型,默认使用Object类型。
5.自定义泛型类时,类型持有者名称可以使用T(Type);
  如果是容器的元素,使用E(Element);
  若键值匹配(hash表)可以使用K(key)与V(Value);
  若是Annotation可以使用A。
三。泛型的高级语法:
1.限制泛型的可用类型:
  在定义类型的持有者时,使用extends指定指定这个类型持有者的实例化,实例化对象必须是扩充自某个类型或实现某个借口
  //ListGenericFoo.java
  import java.util.List;

  public class ListGenericFoo<T extends List>{
  private T[] fooArray;

  public void setFooArray(T[] fooArray){
  this.fooArray = fooArray;
  }

  public T[] getFooArray(){
  return fooArray;
  }
  }
  ListGenericFoo在声明类型持有者时,一并指定这个持有者实例化的对象,必须是实现java.ytil.List接口的类。
  使用extends限制实例化生成的对象,必须是实现List接口的类。如LinkedList,ArrayList;
2.类型通配符(wildcard)
  如果你想有一个foo名称可以参考的对象,其类型持有者实例化的对象是实现List接口的类或者子类,可以使用?(通配符)。
  ?代表未知类型,并使用extends关键词做限定。eg:
  GenericFoo<? extends List> foo = null;
  foo1 = new GenericFoo<ArrayList>();
  ...
  foo2 = new GenericFoo<LinkedList>();
  ...
  如果实例化的对象不是实现List接口的类,则编译器会报告错误。eg:
  GenericFoo<? extends List> foo = new GenericFoo<HashMap>();
  编译器会报如下的错误:
  incompatible types
  found : GenericFoo<java.util.HashMap>
  required:GenericFoo<? extends java.util.List>
  GenericFoo<> foo = new GenericFoo<HashMap>();
  因为HashMap没有实现List接口,所以建立的GenericFoo<HashMap>实例不能指定给foo名称来参考。
  注意:通过使用通配符声明的名称所参考的对象,你没办法再对它加入新的信息,你只能取得或者移除它当中的信息。
  除了可以向下限制,也可以向上限制,使用super实现.eg:
  GenericFoo<? super StringBuilder> foo = null;
  ...
  扩展一个泛型类
  //GenericFoo4.java
  public class GenericFoo4<T1,T2>{
  private T1 foo1;
  private T2 foo2;

  public void setFoo1(T1 foo1){
  this.foo1 = foo1;
  }
  public T1 getFoo1(){
  return foo1;
  }

  public void setFoo2(T2 foo2){
  this.foo2 = foo1;
  }
  public T2 getFoo2(){
  return foo1;
  }
  }
a.如果决定要保留类型持有者,则在子类中必须写齐全
  //Sub1GenericFoo4.java
  public class SubGenericFoo4<T1,T2> extends GenericFoo4<T1,T2>{
  private T3 foo3;

  public void setFoo1(T1 foo1){
  this.foo1 = foo1;
  }
  public T1 getFoo1(){
  return foo1;
  }

  public void setFoo2(T2 foo2){
  this.foo2 = foo2;
  }
  public T2 getFoo2(){
  return foo2;
  }

  public void setFoo3(T3 foo3){
  this.foo3 = foo3;
  }
  public T3 getFoo3(){
  return foo3;
  }
  }
b.如果不保留类型持者,继承下来的T1和T2自动转换成Object。
  //Sub2GenericFoo4.java
  public class SubGenericFoo4<T1,T2> extends GenericFoo4<T1,T2>{
  private T3 foo3;

  public void setFoo3(T3 foo3){
  this.foo3 = foo3;
  }
  public T3 getFoo3(){
  return foo3;
  }
  }
 
3.泛型的本质就是:
  将<font color="#8b0000"></font>所操作的数据类型参数化,也就是说,该数据类型被指定为一个参数。
4.使用泛型的好处在于:
  它在编译的时候进行类型安全检查,并且在运行时所有的转换都是强制的,隐式的,大大提高了代码的重用率。

结束语:因为在看JDK源码时看到大量的泛型使用,所以才找了些基础的泛型介绍,希望网友能举些复杂的泛型示例进行分析,欢迎讨论...
参考资料:《java学习笔记》 林信良著;
                http://blog.csdn.net/bluesmile979/archive/2009/03/10/3976905.aspx
                http://www.ibm.com/developerworks/cn/java/j-djc02113/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值