java泛型

一.为什么使用泛型
1.之前没使用的情况
在泛型出现之前,一旦把一个对象丢进集合中,集合就会忘记对象的类型,把所有的对象当成object类型来进行处理。当程序从集合中取出对象后,就需要进行强制类型转换,这会让代码变得臃肿,同时类型转换的时候也有可能会出现,ClassCastException异常

        ArrayList collection1 = new ArrayList();
        collection1.add(1);
        collection1.add(1L);
        collection1.add("abc");
        //int i = (Integer)collection1.get(1);

2.使用后
很大程度上是为了让集合记住其中元素的数据类型类型,使用了泛型之后,编译器在编译代码的时候,会进行类型检查,如果试图向集合中添加不满足类型要求的对象,编译器会提示类型错误,这提高了代码的安全性;其次使用泛型,可以提高代码的通用性

        ArrayList<String> collection2 = new ArrayList<String>();
        //collection2.add(1);
        //collection2.add(1L);
        collection2.add("abc");
        String element = collection2.get(0);

二.介绍
本质:
1.泛型是给编译器看的,让编译器挡住非法类型的输入,编译器编译带类型说明的集合,生成字节码前会去除掉“类型”信息,使程序的运行效率不受影响
2.对于参数化的泛型类型,getClass()方法的返回值跟原始类型相同

        ArrayList<Integer> collection3 = new ArrayList<Integer>();
        System.out.println(collection3.getClass() == collection2.getClass());//true
        //collection3.add("abc");
        collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc");
        System.out.println(collection3.get(0));

由于编译生成的字节码会去除掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型的集合中加入另一个类型的数据。

collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc");//通过反射将String类型的数据加入到了int集合中

三.泛型中的通配符
使用?可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用参数无关的方法,不能调用参数化有关的方法

public static void printCollection(Collection<Object> c){
     for(Object obj :c){
        System.out.println(obj);
    }
    c.add("abc");//正确
    c  = new ArrayList<String>();//错误
}

public static void printCollection(Collection<?> c){
     for(Object obj :c){
        System.out.println(obj);
    }
    c.size();//正确
    c.add("abc");//错误
    c  = new ArrayList<String>();//正确
}

类型通配符的扩展
ArrayList<? extends Number>
ArrayList<? super Integer>

  HashMap<String,Integer> maps = new HashMap<String, Integer>(); //泛型参数化,不能是基本类型
  maps.put("abc", 28); //此处的28被自动装箱成Integer类型,
  maps.put("bcd", 35);
  maps.put("cdf", 33);

  Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
  for(Map.Entry<String, Integer> entry : entrySet){
   System.out.println(entry.getKey() + ":" + entry.getValue());
  }

四.自定义泛型
1.定义泛型方法

private static <T> T add(T x,T y){ 
  return null;
}

add(3,4); T —Integer
add(3,3.5); T —Number
add(3,”abc”); T —Object

T只能是引用类型,不能是基本类型,上面的基本类型被自动装箱成相应的引用类型

类型限定符的扩展
ArrayList //即使是接口 ,也用extends而不是implements
ArrayList

2.定义泛型类型
如果类中有多个方法使用泛型,使用类级别的泛型

public class GenericDao<E>  {
     public void add(E x){

     }

     public E findById(int id){
             return null;
     }

     public void delete(E obj){

     }

     public void delete(int id){

     }

     public void update(E obj){

     }

泛型类,可以看做普通类的工厂类
当一个变量被声明为泛型时,只能被实例变量跟实例方法调用(也可以被内嵌类型调用),不能被静态变量跟静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有声明为泛型的类型参数
//此处错误
public static void update2(E obj){

 }

//此处正确
public static void update2(E obj){

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值