Learn Java for Android Development Second Edition 笔记(五)

本文深入探讨了Java中多态的四种形式:Coercion、Overloading、Parametric及Subtype,详细解释了Upcasting和LateBinding的概念,并介绍了抽象类与抽象方法的作用。此外,还讨论了Downcasting的安全性及Covariant Return Types的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多态

Java里提供四种类型的多态方法,
  • Coercion,就是数据类型显示或隐式转换
  • Overloading,函数名称相同,但是参数不同
  • Parametric,就是类似C++模板,Java通过generics来实现。
  • Subtype,一种类型可以作为另一种类型的subtype起作用。当subtype对象出现在父类的上下文中时,在subtype对象上执行父类的操作,会导致subtype上对应的操作执行。例如,假设Circle是Point的子类,都有draw方法,将一个Circle对象赋值给一个Point对象,然后调用该Point对象的draw方法,会导致真正调用Circle的draw方法。

Upcasting和Late Binding

Circle对象有x,y坐标,可以是Point的子类,再加上radius变量。
Circle c = new Circle(10, 20, 30);
Point p = c;
将Circle对象转换为Point对象时,不需要cast,因为Circle至少是一个Point,这种转换就被称为upcasting(将子类对象赋值给父类对象)。
以上方法就实现了subtype多态,但p对象也失去了部分子类特有的feature,这是subtype的代价。subtype除了将子类对象赋值给父类对象外,还需要在子类对象里override
父类的draw方法(在Point这个例子里)。
这时,调用p的draw方法时,实际上会去执行Circle类里的draw方法。
p对象是怎么知道去调用Circle类里的draw方法呢?在编译的时候,编译器是不知道去调用哪个方法的,它能做的就是检查p里面是否有这个方法并且参数和返回值正确,然后在这个地方插入一条指令,让Java在运行时,去获取该对象的正确引用,并调用正确的draw方法。这个任务被称作late binding
Late binding用于所有非final的对象方法,对于其他方法,编译器知道调用哪个具体类的方法,这个任务被称作early binding

Abstract Classes and Abstract Methods

如果要在Circle和Point类的基础上,再实现一个Rectangle类,这个时候不大适合再去extend Point类,因为矩形不适合表示成一个点加上长宽。
因为Circle,Point和Rectangle都是一种图形Shape且都有各自的draw方法。因此可以实现一个Shape class来让另外三个继承:
class Shape
{
void draw()
{
}
}
Shape[] shapes = new Shape[] { new Point(10, 20), new Circle(10, 20, 30),
new Rectangle(20, 30, 15, 25) };
上面Shape对象有个问题,但有用户直接new Shape(),这个是没有意义的,为了预防这种情况,Java提供了抽象类的概念。
abstract class Shape
{
abstract void draw(); // semicolon is required
}
abstract关键字表示这个对象不能直接实例化。abstract也可以用于没有实际内容的成员函数。
关于抽象类的几个注意事项
  • abstract和final不能用于同时声明一个类,因为abstract表示一个类不能直接对象化,而final表示一个类不能被继承,这就是矛盾的。
  • 当声明一个成员函数是abstract时,也要声明它所属的类是abstract。一个具体的类不能包含一个抽象的成员函数。
  • 当继承一个抽象类时,要么实现它所有的抽象成员函数,要么自己也声明为一个抽象类。
  • 一个抽象类可以包含非抽象的成员函数。

Downcasting and Runtime Type Identification

Circle c = (Circle) p;
上面把Point类型转换成Circle类型(父到子)称作downcast,downcast有时候是安全的,例如p本身原来是由Circle类型转换来的,现在只是再转换回去。有些时候是不安全的,例如当p本身最开始就是Point类型,而转换成Circle c后,c再调用Circle里特有的函数时,系统就会扔出异常,此时可以通过instanceof关键字来判断是否可以安全的进行downcast。例如以下例子:
public class DowncastArrayDemo
{
public static void main(String[] args)
{
ColoredPoint[] cptArray = new ColoredPoint[1];
cptArray[0] = new ColoredPoint(10, 20, 5);
Point[] ptArray = cptArray;
System.out.println(ptArray[0].getX()); // Output: 10
System.out.println(ptArray[0].getY()); // Output: 20
// System.out.println(ptArray[0].getColor()); // Illegal
if (ptArray instanceof ColoredPoint[])
{
ColoredPoint cp = (ColoredPoint) ptArray[0];
System.out.println(cp.getColor());
}
}
}

Covariant Return Types

一种可以消除downcast和upcast的方法???



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值