zoukankan      html  css  js  c++  java
  • 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中没有所谓的泛型数组一说。

  • 相关阅读:
    spark 读取mongodb失败,报executor time out 和GC overhead limit exceeded 异常
    在zepplin 使用spark sql 查询mongodb的数据
    Unable to query from Mongodb from Zeppelin using spark
    spark 与zepplin 版本兼容
    kafka 新旧消费者的区别
    kafka 新生产者发送消息流程
    spark ui acl 不生效的问题分析
    python中if __name__ == '__main__': 的解析
    深入C++的new
    NSSplitView
  • 原文地址:https://www.cnblogs.com/yuxin-555xt/p/6528216.html
Copyright © 2011-2022 走看看