• java中的泛型


    http://www.cnblogs.com/lzq198754/p/5780426.html      http://www.cnblogs.com/lwbqqyumidi/p/3837629.html

    1.java中的泛型,为什么会出现泛型? (参数化类型,泛型一般在集合中会被经常用到)

    //没有使用泛型
    public
    class FanxingTest { public static void main(String[] args){ List tempList = new ArrayList(); tempList.add("abcde"); tempList.add(100); for(int i=0;i<tempList.size();i++){ String tempStr = (String)tempList.get(i); //此处需要强制类型转换 } } }

    以上如果没有使用泛型,程序中会需要出现强制类型转换。而且不小心放入一个Integer类型的值,会出现java.lang.ClassCastException(强制类型转换错误)异常。

    //使用泛型
    public
    class FanxingTest { public static void main(String[] args){ List<String> tempList = new ArrayList<String>(); tempList.add("abcde"); //tempList.add(100); for(int i=0;i<tempList.size();i++){ String tempStr = tempList.get(i); } } }

    以上使用了泛型<String>将这个List规范成只有String类型,只有String类型的值才能被放入到这个List里边,当执行tempList.add(100);时会出现一个编译错误,所以在这样可以保证在运行时不会出现ClassCastException异常。所以使用泛型可以保证程序的质量,减少程序出现运行时错误。

    2.泛型只在程序编译是起作用,在程序运行时会将泛型擦除:

    public class FanxingTest {
        public static void main(String[] args){
            List<String> tempList1 = new ArrayList<String>();     //String类型
            List<Integer> tempList2 = new ArrayList<Integer>();   //Integer类型
            System.out.println(tempList1.getClass().getName());
            System.out.println(tempList2.getClass().getName());
            System.out.println(tempList1.getClass().getName() == tempList2.getClass().getName());
        }
    }
    //输出结果
    java.util.ArrayList
    java.util.ArrayList
    true

    有以上代码可以看出,List的泛型在代码运行时是没有起作用的,输出两个不同泛型的类型是一样的,都是java.util.ArrayList。所以说泛型只在代码编译的时候存在,在运行时被擦除。

    通过java反射机制的原理也可以证明:

    public class FanxingTest {
        public static void main(String[] args){
            List<String> tempList = new ArrayList<String>();
            tempList.add("abcde");
            Class c = tempList.getClass();   //获取tempList对象的类型c
            try {
                Method method = c.getMethod("add", Object.class);  //给这个类c添加一个方法
                method.invoke(tempList, 100);   //在tempList这个对象上调用这个方法
                System.out.println(tempList);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    //输出结果
    [abcde, 100]

    以上通过反射机制实现,绕过了编译阶段也就绕过了泛型,虽然tempList是String类型的List,但是通过反射机制还是可以将integer类型的值放进去,而且没有报错,所以再一次证明泛型是在编译时有效,在运行时无效。

    3.泛型不可以是基本数据类型的

    因为当不加泛型的时候,默认是Object类型的,是类类型的,所以泛型不能够是基本数据类型的。

    List<int> tempLiat = new ArrayList<int>();  //是会报错的,不能够这样写

    4.泛型接口,泛型类和泛型方法(都可以自己定义)

    //自定义泛型类和泛型方法
    public class FanxingTest<T> {
        private T obj;
        public FanxingTest(T tempObj){
            this.obj = tempObj;
        }
        public T getObj() {
            return obj;
        }
        public void setObj(T obj) {
            this.obj = obj;
        }

        public void getData(FanxingTest<Number> fff){
            System.out.println(fff);
        }
        public static void main(String[] args){
            FanxingTest<Number> temp1 = new FanxingTest<Number>(100);
            Number str = temp1.getObj();
            FanxingTest<Integer> temp2 = new FanxingTest<Integer>(200);
            Integer num = temp2.getObj();
            
            temp1.getData(temp1);
            
            //temp2.getData(temp2);  //会报编译时错误
        }
    }

    以上是自定义的泛型类和泛型方法,在main方法中分别使用泛型创建了两个对象temp1和temp2,虽然Number是Integer的父类,但是当temp2.getData(temp2)时会报编译时错误。在泛型中只能使用定义好的类型。所以在泛型的理念中:在逻辑上FanxingTest<Number>不能视为FanxingTest<Integre>的父类。

    5.这是通配符就应用而生(格式类似:FanxingTest<?>)

    //自定义泛型类和泛型方法
    public class FanxingTest<T> {
        private T obj;
        public FanxingTest(T tempObj){
            this.obj = tempObj;
        }
        public T getObj() {
            return obj;
        }
        public void setObj(T obj) {
            this.obj = obj;
        }
    
        public void getData(FanxingTest<?> fff){
            System.out.println(fff);
        }
        public static void main(String[] args){
            FanxingTest<Number> temp1 = new FanxingTest<Number>(100);
            Number str = temp1.getObj();
            FanxingTest<Integer> temp2 = new FanxingTest<Integer>(200);
            Integer num = temp2.getObj();
            
            temp1.getData(temp1);
          temp2.getData(temp2);
    } }

    运用了通配符之后,temp2.getData(temp2);就不会报错了。

    类型通配符一般是使用 ? 代替具体的类型实参。注意了,此处是类型实参,而不是类型形参!且Box<?>在逻辑上是Box<Integer>、Box<Number>...等所有Box<具体类型实参>的父类。由此,我们依然可以定义泛型方法,来完成此类需求。

    还有通配符上限 FanxingTest<? extends Number>

    还有通配符下限 FanxingTest<? super Integer>

    6.注意:Java中没有所谓的泛型数组一说。

  • 相关阅读:
    Cxx11 stdchrono库详解
    Oracle中文乱码
    Javascript 编程小技巧总结(部分内容借鉴他人)
    从文档流角度理解浏览器页面渲染引擎对元素定位的解析
    JS重点特性——闭包详解
    用一段JS代码来比较各浏览器的极限内存与运算速度
    前端开发人员需知——浏览器详解
    Js变量定义——fn里 var与不var的区别
    Js文字特效—文字段逐个变色循环
    html5 canvas画图之图形随拖动而复制(有操作指示)
  • 原文地址:https://www.cnblogs.com/yuxin-555xt/p/6528216.html
Copyright © 2020-2023  润新知