重载Overloading
发生要素如下:
1. 在同一作用范围内(同一个类,同一个接口)
2. 方法名必定相同
3. 形参组成不同(类型、个数均不相同 or 个数相同但类型不同 or 类型相同个数不同)
错误的认识:
1. 方法名相同,形参组成完全相同,返回类型不同也算重载(方法重载要求方法具有不同的签名:形参组成,而返回值并不算作签名内容,故不参与重载的选择)
2. abstract修饰必须存在才算重载方法(无所谓啊,修饰符惹谁了?)
abstract class AbstractBase {
abstract void add();
abstract void add(int a); //OK
void add(String b){} //OK
int add(String b){} // NO!!!编译不通过
protected void add(int a,int b){}
}
覆盖/重写/覆写(一个意思!)(Overriding/Overwrite)
发生要素如下:
1. 不同作用范围内(继承别的类,实现接口)
2. 方法名相同(废话!)
3. 形参组成相同(类型、个数均相同)
4. 返回类型相同
个人理解:
1. 既然是覆盖,要完全盖住,学的像点,所以方法的外表要看上去一样嘛。
2. 实现接口方法,也可称为覆盖,毕竟是把空的方法体覆盖为具体的代码了。想想也是,实现接口的时候IDE是不是为我们自动加上了@Override注解?这个在JDK6之前的版本可不行,写这个注解是会报错的。(怀念起在老东家运维JDK1.5项目的时光)
要注意的地方:派生方法不能抛出比基类方法范围更广的异常(速记:孩子不能闯比父母更大的祸),
错误范例:基类方法throws IOException,派生方法却throws Exception。
派生方法不能有比基类方法更大的访问度(速记:孩子不能比父母更能显摆),
错误范例:基类方法是protected,派生方法却是public。
隐藏Hiding
发生要素如下:
1. 同覆盖的1.2.3.4条件(必要)
2. 仅发生在静态方法上
要点:
隐藏不需要@Override注解修饰,加上会报错。且派生方法的可抛出异常范围和可访问范围的约束与覆盖相同(不能抛更多异常,不能有更广的访问权限)。
在jls11文档中,隐藏注明为 by Class Methods,而覆盖则是by Instance Methods,这个很好理解,静态的成员方法就是属于这个类的,隐藏也可以叫类的方法的覆盖。
个人理解:静态方法是和类绑定到一起的,那么在实例化的时候,用的谁的类型的引用,那么call到的方法就是谁的实现,也许说的不恰当,请看下例:
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Kick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
//输出:Goodnight, Kick
Sub s2 = new Sub();
System.out.println(s2.greeting() + ", " + s.name());
//输出:Hello, Kick
}
}
由于s的类型是Super,所以greeting()执行的是Super的实现,但是name()是正常的覆盖,好比派生类没有重写greeting()一样(派生类干的事儿被藏起来了)。但是s2 call到的就是Sub的实现了,符合常规的思路。
本文参考:jsl11文档