java子类型多态
三种多态:
多态性是指为不同类型的实体提供一个接口,或者使 用一个符号来表示多个不同的类型。
- 一个函数可以有多个同名的实现(方法重载)
- 一个类型名字可 以代表多个类型(泛型编程)
- 一个变量名字可以代表多个类的实例(子类型)
子类型的Liskov Substitution Principle (LSP)原则
- 子类型可以添加,但不能删除方法
- 具体类必须实现所有未定义的方法
- 重写方法必须返回相同的类型或子类型
- 重写方法必须接受相同的参数类型
- 覆盖方法可能不会引发其他异常
也可以写成 - 相同或更强的不变量RI
- 所有方法的相同或更强的后置条件
- 所有方法的相同或较弱的前提条件
型变(这里说的不是java,只是三种型变类型)
- 协变:A是B的子类,则A中的参数也是B中参数的子类
- 逆变:A是B的子类,则A中的参数是B中参数的父类
- 不变:A是B的子类,则A中的参数与B中参数类型一致
泛型
- 虚拟机中没有泛型类型对象-所有对 象都属于普通类!泛 型信息只存在于编译阶段,在运行时会被”擦除” 。类型变量会被擦除,替换为限定类型,如果没 有限定类型则为Object类型。所以运行时类型查询 只适用于原始类型,不适用于泛型,下面是两个例子
- Java中的泛型是不“型变”的。
已知Number类型是Integer的父类。可以知道Number[]类型是Integer[]的父类,但是List<Integer>不是List<Number>的子类。原因就是List是泛型,而泛型不“型变”。
通配符:?
List<?> 或 List<? extends Animal> 或List<? super Animal>,其中Animal是一个自定义的类。
通配符可以视作协变。若Cat作为Animal的子类,WhiteCat的父类,则List<Cat>是List<? extends Animal> 的子类,是List<? super WhiteCat>的父类。现在以Animal(爹)、Cat(子)、WhiteCat (孙子)为例大致说一下注意点:
- List<? extends Animal>:List<Cat>与List<WhiteCat>都可以是它的子类。它可以调用get方法,但是不能调用增加(add)或者改变(set)的方法,
– 调用一个返回Animal类型(或子类型)的方法(如 :T get(int pos))是安全的, 因为compiler知道这个List中的任何对象至少具有 Animal类型(或子类型),可以完成类型转换。
– 但调用类似add(E e)的方法则不安全,类型擦除机制会导致运行时可以往animals中储存 各种类型的对象。 所以就直接不让加入了。 - List<? super Cat>:List<Animal> 是它的子类。
– 调用add等方法的时候,可以加入Cat或其子类;
– 调用get方法时候,得到的东西必须强转。由于不知道里面是什么,强转不安全,因此不要随便用
注意,? extends Animal不是一个类,只能用于泛型中(我学过的地方只能这么做)
说点什么
前几天学了一点关于子类的东西,今天又看了一些。主要学习了通配符的使用以及LSP规则。关于通配符中List<? super Cat>的理解以前一直有错误。以为不能使用get方法,后来发现不是这个意思,是get之后返回了一个Object的类型(我是这么理解的。应该是类型擦除成什么样返回什么),只有使用强转才能变为想要的类型。