• 【Java基础】泛型的一些总结


    什么是泛型

    泛型其实可以理解为一种广泛的类型,啥类型都型,当然,这种泛是指定义时可以广泛,但是使用时必须确定类型。也就是说,当不清楚未来使用哪种类型时,定义为泛型。可以支持泛型类,泛型接口,泛型方法,泛型成员变量。

    泛型的好处

    1. 泛型可以将类型作为参数进行传递,即类型可以像参数一样实现参数化。 
    2. 泛型能提高代码的重用。
    3. 在编译的时候检查类型安全,把运行期的问题提前展现出来。
    4. 泛型中的强制转换都是自动和隐式的 

    下面用几个示例来表明这几种好处:

    下面的代码表示的是代码重用的案例,几个传入不同类型的a都可以用泛型T表示。

        public void show(int a){
            System.out.println(a);
        }
    
        public void show(Boolean a){
            System.out.println(a);
        }
        public void show(String a){
            System.out.println(a);
        }
    
        public void show(T a){
            System.out.println(a);
        }

    下面这段代码在编译期间是不会出错的,因为集合中可以传入任何对象,但是一运行就会出错,因为后面遍历时进行强制转换为Integer,String是不能强转为Integer的。

            List s = new ArrayList();
            s.add(1);
            s.add(2);
            s.add("hello");
            Iterator it = s.iterator();
            int sum = 0;
            while (it.hasNext()){
                Integer i = (Integer) it.next();
                sum += i;
            }

    但是由于ArrayList是泛型类,如果在定义的时候提前确定将来要存储在List中的类型,则可以提前提示出错误,这个就类似我们定义数组,刚开始就确定了数组的类型。

    自动强制用的最多的地方就是在Iterator时规定了迭代的类型,所以在遍历时不用做强转工作,会自动强转。

            List<Integer> s = new ArrayList();
    
            s.add(1);
            s.add(2);
    //        s.add("hello");
            Iterator<Integer> it = s.iterator();
            int sum = 0;
            while (it.hasNext()){
    //            Integer i = (Integer) it.next();
                sum += it.next();//由于Integer中规定了类型,这里会自动强制转换
            }

    泛型类(Object和泛型类的区别--思考引入泛型的原因)

    Object也可以代替任何类型,那Object是否可以取代泛型呢?接下来看一个示例程序:

    public class Test {
        public static void main(String[] args) {
            Animal animal = new Animal();
            animal.setAttr(3);
            Integer age = (Integer) animal.getAttr();
            System.out.println(age);
    
            System.out.println("---------------------");
            animal.setAttr("dog");
            String kind = (String) animal.getAttr();
            System.out.println(kind);
    
            System.out.println("---------------------");
            animal.setAttr("kity");
            Integer name = (Integer) animal.getAttr();//不按常规出牌,编译不报错
            System.out.println(name);
    
        }
    }
    
    class Animal {
        private Object attr;
    
        public Animal() {
        }
    
        public Object getAttr() {
            return attr;
        }
    
        public void setAttr(Object attr) {
            this.attr = attr;
        }
    }

      明显Test中最后一段设置姓名是String,但是做强转可能没搞清楚,偏偏转到Integer了,但是这个时候是不会报错的,因为编译期间Object是可以向子类Integer向下转型的。但是运行时就会报错,所以利用Object来写这种程序是不安全的。但是如果将Object替换为泛型,则会在编译期间就会报错。

      上述代码,如果将Animal定义为泛型类,即将Object都替换为泛型支持,并在Animal后面加上尖括号<T>,于此同时保持测试代码不变,依然编译期间不会报错,这说明,如果不指定T的类型,默认应该还是将T换成了Object。

      但是,泛型类的使用规则是需要你定义的时候就规定将来的类型的,在定义时讲T确定为Integer后,上述代码有三行编译出错。

    public class Test {
        public static void main(String[] args) {
            Animal<Integer> animal = new Animal<>();
            animal.setAttr(3);
            Integer age = (Integer) animal.getAttr();
            System.out.println(age);
    
            System.out.println("---------------------");
            animal.setAttr("dog");//编译不通过
            String kind = (String) animal.getAttr();//编译不通过
            System.out.println(kind);
    
            System.out.println("---------------------");
            animal.setAttr("kity");//编译不通过
            Integer name = (Integer) animal.getAttr();
            System.out.println(name);
    
        }
    }
    
    class Animal<T> {
        private T attr;
    
        public Animal() {
        }
    
        public T getAttr() {
            return attr;
        }
    
        public void setAttr(T attr) {
            this.attr = attr;
        }
    }

    泛型方法

      泛型类有一个特点,就是需要在实例化类的时候明确泛型的类型,不然有警告(不然就是当作Object),一旦定义了,接下来类中的所有泛型的T都确定了。也就是说如果实例化的时候将T定义为String,则类中所有的T都是String,这样不是太灵活。所以引入了泛型方法。

      泛型方法的定义特征:public static <T> List<T> asList(T... a)

         这里用Arrays中的asList方法来举例说明,泛型方法是将以前泛型类中的<T>放到了方法返回值前面。这样asList方法以后可以接受任何类型的传参了。

         ps:这篇文章对泛型方法进行了更深入的总结http://www.cnblogs.com/iyangyuan/archive/2013/04/09/3011274.html

    泛型接口

    泛型接口和泛型类类似,只是实现泛型接口的类一般也是继续泛型下去,如若不然,则泛型接口的灵活性就没有被突显了。

    public interface Animal<T> {
        public abstract void show(T a);
    }
    public class Dog<T> implements Animal<T>{
    
        @Override
        public void show(T a) {
            System.out.println(a);
        }
    }

    泛型的高级运用-通配符

    
     1. ?:            任意类型,如果没有明确,那么就是Object以及任意的Java类了
     2. ? extends E:  向下限定,E及其子类
     3. ? super E:    向上限定,E极其父类
     
    public class GenericDemo {
        public static void main(String[] args) {
            // 泛型如果明确的写的时候,前后必须一致
            Collection<Object> c1 = new ArrayList<Object>();
            // Collection<Object> c2 = new ArrayList<Animal>();
            // Collection<Object> c3 = new ArrayList<Dog>();
            // Collection<Object> c4 = new ArrayList<Cat>();
    
            // ?表示任意的类型都是可以的
            Collection<?> c5 = new ArrayList<Object>();
            Collection<?> c6 = new ArrayList<Animal>();
            Collection<?> c7 = new ArrayList<Dog>();
            Collection<?> c8 = new ArrayList<Cat>();
    
            // ? extends E:向下限定,E及其子类
            // Collection<? extends Animal> c9 = new ArrayList<Object>();
            Collection<? extends Animal> c10 = new ArrayList<Animal>();
            Collection<? extends Animal> c11 = new ArrayList<Dog>();
            Collection<? extends Animal> c12 = new ArrayList<Cat>();
    
            // ? super E:向上限定,E极其父类
            Collection<? super Animal> c13 = new ArrayList<Object>();
            Collection<? super Animal> c14 = new ArrayList<Animal>();
            // Collection<? super Animal> c15 = new ArrayList<Dog>();
            // Collection<? super Animal> c16 = new ArrayList<Cat>();
        }
    }
    
    class Animal {
    }
    
    class Dog extends Animal {
    }
    
    class Cat extends Animal {
    }
  • 相关阅读:
    [转载]Oracle Golden Gate
    git操作命令
    logger.error完整打印错误堆栈信息
    短网址算法
    YYYY-mm-dd HH:MM:SS大小写解释
    quarz时间配置
    Freemarket语法
    Java NIO:IO与NIO的区别
    idea常用到的命令
    linux 常用命令
  • 原文地址:https://www.cnblogs.com/gslyyq/p/4970286.html
Copyright © 2020-2023  润新知