zoukankan      html  css  js  c++  java
  • java 泛型类的继承关系和转型问题

    两个问题

    问题一:FatherClass和ChildClass是父子类的关系,那List<FatherClass>和List<ChildClass>是否也是父子类的关系?

    问题二:倘若不是父子类关系,那么通过什么方式可以达到向上转型的效果?

    有两个类Fruit和Apple,Apple继承自Fruit,所以Fruit使Apple的父类,关系如下图所示

    示例代码

    public class GenericMain {
    
        public static void method1(Fruit fruit) {
            System.out.println("lingyejun eat fruit");
        }
    
        public static void method2(List<Fruit> fruitList) {
            System.out.println("lingyejun eat fruit list");
        }
    
        public static void method3(Collection<Fruit> fruitList) {
            System.out.println("lingyejun eat fruit collection");
        }
    
        public static void method4(List<? extends Fruit> fruitList) {
            System.out.println("lingyejun eat extends fruit list");
        }
    
        public static void main(String[] args) {
            method1(new Fruit());
            method1(new Apple());
    
            List<Fruit> fruitList = new ArrayList<>();
            fruitList.add(new Fruit());
            method2(fruitList);
    
            List<Apple> appleList = new ArrayList<>();
            appleList.add(new Apple());
            method2(appleList);// Compile Error
    
    
            method3(fruitList);// 可以向Collection<Apple>中传入List<Apple>
            Set<Fruit> fruitSet = new HashSet<>();
            method3(fruitSet);// 也可以向Collection<Apple>中传入Set<Apple>
    
            method4(fruitList);
            method4(appleList);
        }
    }

    method1的方法参数是Fruit类型,想method1方法中传递Fruit类型的变量或者Apple类型的变量都是可以的,因为Apple继承自Fruit,会进行向上类型转换。

    method2的方法参数时List<Fruit>,我们试图传递List<Apple>类型的变量是会出现编译报错,因为List<Fruit>和List<Apple>并不存在所谓的父子关系,是两种无关的类型,所以编译会报错。 

    集合类的继承关系

    对于泛化的集合类型他们的继承关系,以Collection<E>为例,ArrayList<E>实现了List<E>, 同时 List<E> 扩展自 Collections<E>。故 ArrayList<E>是 List<E>的子类型,List<E>是Collections<E> 的子类型。只要类型参数E一致,这三个类的继承关系就得到保持。如下图所示左右分别是Collection<Fruit>和Collection<Apple>的继承链路。他们两个是相互独立的,没有交叉的两条关系链路,所以尝试在method2中传入appleList会编译报错。

    同理,我们如果定义一个method3的参数列表为Collection<Fruit>,那么按照集合的继承体系,方法参数中可以传入泛型类型为Fruit的Collection下的所有子类型。

     如果有这样的需求List<Fruit>和List<Apple>想使用同样的方法,那么我们该怎么样定义参数列表呢?

    可以使用extends关键字来限制泛型参数的适用范围,List<T extends Fruit> 表示泛型实际参数可以是所有继承自Fruit的类,如lApple等。

    小结

    泛型类和普通类一样,可以扩展或实现其他的泛型类或接口。ArrayList<E>实现了List<E>接口,一个ArrayList<Apple>可以转化为List<Apple>,而一个ArrayList<Apple>并不是一个List<Fruit>或者ArrayList<Fruit>。

    如果我们要实现List<Fruit>和List<Apple>之间的关联,可以使用泛型通配符在定义方法的时候指明这个List<? extends Fruit>来实现关联。

    本篇文章如有帮助到您,请给「翎野君」点个赞,感谢您的支持。

  • 相关阅读:
    Linux Namespace : IPC
    Linux Namespace : UTS
    Linux Namespace : 简介
    《Two Dozen Short Lessons in Haskell》(二十四)代数类型
    为期近五个月的英语培训班总结
    GTD实践2周年后一些体会
    读书笔记2013第10本:《学得少却考得好Learn More Study Less》
    读书笔记2013第9本:《注意力曲线----打败分心与焦虑》
    《Two Dozen Short Lessons in Haskell》(二十二)递归
    GIF图片合集(用于网络请求图片用)
  • 原文地址:https://www.cnblogs.com/lingyejun/p/14222676.html
Copyright © 2011-2022 走看看