方法重载(Overload)
Java中的方法重载:方法名相同,参数列表不同
功能相似的方法,只需记住一个方法名,通过参数列表区分
方法签名:方法名 + 参数列表,用来区分不同方法的标识符
一、方法重载因素
有关因素:参数个数、参数类型、参数的多类型顺序不同
无关因素:方法的访问修饰符、方法的返回值类型、参数名称
二、方法重载示例
System.out.println()方法是一个很好地运用方法重载的示例
println方法可以打印各种类型的数据,只需记住一个方法名
三、避免重载歧义
- add(10, 20.0)、add(10.0, 20),正常执行
- add(10, 20); // 标红报错 Ambiguous method call.
public static void add(int a, double b) {
System.out.println(a + b);
}
public static void add(double a, int b) {
System.out.println(a + b);
}
方法重写(Override)
Java中的方法重写:方法名相同,参数列表相同
方法重写发生在子类中,方法重载发生在本类中,注意从父类继承过来的方法
子类通过方法重写隐藏继承的方法,把父类的状态和行为改变为自身的状态和行为
- 子类重写父类的方法f,隐藏继承的方法f,子类对象调用方法f调用的是重写方法f
- 子类没有重写方法,子类对象可以调用继承的方法f,方法产生的行为和父类的相同
// 父类 普通商品
public class Goods {
private double weight;
/**
* 物品称重
*
* @param weight
*/
public void setWeight(double weight) {
this.weight = weight;
}
/**
* 计算价格
*
* @return
*/
public double getPrice() {
return weight * 20; // 普通商品单价20元
}
}
// 子类 打折商品
public class CheapGoods extends Goods {
private int weight;
/**
* 物品称重
*
* 方法重载:方法名相同,参数列表不同
* 继承过来的setWeight(double weight)和子类定义的setWeight(int weight)构成重载关系
* @param weight
*/
public void setWeight(int weight) {
this.weight = weight;
}
/**
* 计算价格
*
* 方法重写:方法名相同,参数列表相同
* 访问权限不能低于父类、返回值类型与父类一致或是子类型
* 异常类型与父类一致或是子类型,或者子类重写的方法不声明异常
* @return
*/
@Override
public double getPrice() {
return weight * 10; // 打折商品单价10元
}
}
一、注意事项
访问权限不能低于父类、返回值类型与父类一致或是子类型
所谓子类型,是指如果父类方法的类型是 “类” ,允许重写方法的类型是 “子类”
public class A {
public Object f(int x, int y) {
System.out.printf("%d+%d=%d\n", x, y, x + y);
return null;
}
}
public class B extends A {
@Override
// public Object f(int x, int y) { // 返回值类型与父类方法类型一致
public String f(int x, int y) { // 返回值类型是父类方法类型的子类型
System.out.printf("%d*%d=%d\n", x, y, x * y);
return null;
}
}
异常类型与父类一致或是子类型,或者子类重写的方法不声明抛出异常
不遵守这个规则,将会导致编译器报错或者在运行时无法正确处理异常
- 父类方法没有抛出任何异常,子类方法抛出异常
- 父类方法抛出 A 类型的异常,子类方法抛出与 A 类型无关的异常类型
- 父类方法抛出 A 类型的异常,子类方法抛出 A 类型的超类的异常类型
/**
* 编译时异常:在编译时(写代码时)必须显式处理
* 运行时异常:在运行时才会被检测到,编译器不要求必须处理
*/
public class Parent {
/**
* 父类方法没有抛出任何异常
* java.sql.SQLException extends java.lang.Exception
* java.lang.RuntimeException extends java.lang.Exception
*/
public void methodA() {
System.out.println("methodA in Parent...");
}
/**
* 父类方法抛出 A 类型的异常
* java.net.SocketException extends IOException extends Exception
* java.io.FileNotFoundException extends IOException extends Exception
*
* @throws FileNotFoundException
*/
public void methodB() throws FileNotFoundException {
System.out.println("methodB in Parent...");
}
}
class Child extends Parent {
@Override
public void methodA() throws RuntimeException { // 运行时异常 程序正常
System.out.println("methodA in Child...");
}
// @Override
// public void methodA() throws SQLException { // 编译时异常 标红报错
// System.out.println("methodA in Child...");
// }
@Override
// public void methodB() { // 子类重写的方法不声明异常
public void methodB() throws RuntimeException { // 运行时异常 程序正常
System.out.println("methodB in Child...");
}
// @Override
// 标红报错 子类方法抛出与 A 类型无关的异常类型
// public void methodB() throws SocketException { // 编译时异常 标红报错
// System.out.println("methodB in Child...");
// }
// @Override
// 标红报错 子类方法抛出 A 类型的超类的异常类型
// public void methodB() throws IOException { // 编译时异常 标红报错
// System.out.println("methodB in Child...");
// }
public static void main(String[] args) {
Parent parent = new Child();
try {
parent.methodB(); // 上转型对象调用子类重写的方法
} catch (FileNotFoundException e) {
// 默认捕获的是父类方法抛出的异常 FileNotFoundException
// 重写方法抛出的是运行异常 RuntimeException,没有捕获到
// catch 子句中的参数类型改成 Exception,就能正确处理异常
}
}
}