泛型详解

来源:互联网 发布:局域网即时通信软件 编辑:程序博客网 时间:2024/04/27 14:55

通过引入泛型,我们可以获得的优势: 泛型是在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对象,你就必须得进行         //强制类型转换才能使用,而泛型就是设计出来不让你再进行强制类型转换的,这是矛盾的,所以不能加入信息    }}
0 0
原创粉丝点击