泛型详解

通过引入泛型,我们可以获得的优势: 泛型是在JDK 1.5之后引入的
编译时类型的安全
和运行时更小的抛出ClassCastExceptions的可能。

泛型是变量类型的参数化

泛型是解决什么问题的,
我们都知道一个集合可以添加不同类型的对象,但是在获取对象的时候,必须要知道所有对象的类型才可以取出来,存进去没什么代价,但是取出来的时候代价太大,泛型就是解决集合中存在不同类型对象时的存取问题。

public class GenericityTest {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(1);
        list.add("sss");
        list.add(false);
        for(int i=0;i < list.size();i++){
            String s1=(String)list.get(i);  // 会抛出类型异常
            System.out.println(s1);
        }
    }

}

能用泛型的时候一定要使用泛型,尤其是在使用集合的时候

在定义泛型类别的时候,预设可以使用任何的类型来实例化泛型中的类型,但是如果想要限制泛型类别的使用类型,只能用某个特定类型或者其子类型才能实例化该类型的时候,可以在定义类型的时候,使用extends关键字指定这个类型必须是继承自某个类或者实现了某个接口
下面的例子详细的讲解了泛型。

需要注意的是 在下面的例子中,虽然List是接口,但是在泛型中也必须使用extends关键字表明,这是语法要求

public class GenericityTest2<T extends List>{

    public static void main(String[] args) {
           // ArrayList也是使用了泛型实现的,要求以后在使用集合的时候一定要使用泛型
          ArrayList<String> list = new ArrayList<String>();
          // 使用了泛型之后必须使用它所规定的类型,否则程序编译不通过
         //    list.add(100);  错误的
          list.add("aaa");
          list.add("bb");
          for(Iterator<String> iter = list.iterator(); iter.hasNext();){
              //   String s1 = (String)iter.next();   未使用泛型时,需要对iter.next() 进行强制类型转换,因为返回的是一个Object对象
              //  使用了泛型,就不必再进行强制类型转换,因为系统已经知道对象的类型是String类型
              String s1 = iter.next();
              System.out.println(s1);
          }
          HashMap<String,String> hash = new HashMap<String, String>();
          hash.put("aa","aaa");
          hash.put("bb","bbb");

          // GenericityTest2<T>  如果这样书写,那么他可以传进任意类型的数组,
          //  但是  GenericityTest2<T extends List>  就对传进来的类型做了要求,传进来的对象类型必须是实现了 List接口的
          GenericityTest2<ArrayList<String>> a = new GenericityTest2<ArrayList<String>>();
          //  因此当传进来一个HashMap后程序报错,因为HashMap没有实现List 接口
          //  List 是接口,但是在泛型中依旧使用extends 来声明,记住
          // GenericityTest2< HashMap<String,String>> b = new GenericityTest2< HashMap<String,String>>();

       }
       private T[] t;
       public T[] getT() {
          return t;
      }
      public void setT(T[] t) {
          this.t = t;
     }

    }

当泛型没有指定泛型继承的类型或接口时,默认是 extends Object

GenericTest3

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class GenericTest3<T> {
     private T foo;

    public T getFoo() {
        return foo;
    }

    public void setFoo(T foo) {
        this.foo = foo;
    }
     public static void main(String[] args) {
         // 可以实现与 GenericTest3<T extends List>一样的功能,必须是实现了List的接口的
         GenericTest3<? extends List> ge =null;
         ge=new GenericTest3<ArrayList>();
         ge=new GenericTest3<LinkedList>();

         GenericTest3<String> ge2 =null;
         ge2.setFoo("String");
         GenericTest3<? extends Object> ge3;
         // 上面一句的等价 ==GenericTest3<? > ge3     一般都是使用这个,默认是继承Object的
         // 设置为空,或者将一个特定类型的提取到ge3是没有什么问题的
         ge3=null;
         ge3=ge2;
         // 但是利用它来进行对子类类型的对象赋值时,程序会报错
//       ge3.setFoo("String"); 这样是编译错误的,原因是ge3只知道它是一个实现了Object的对象,
         // 即是Object的一个子类,但不确定是什么类型,因此编译器不让加入信息,如果你能加入信息的话
         // 系统就会认为你已经知道了它的类型,当你调用ge3.getFoo,返回的是一个Object对象,你就必须得进行
         //强制类型转换才能使用,而泛型就是设计出来不让你再进行强制类型转换的,这是矛盾的,所以不能加入信息


    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值