面向对象的三大特征:封装,继承和多态。多态是面向程序设计中代码重用的一个重要机制,它表示当同一操做做用在不一样对象时,会有不一样的语义。java
Java 多态主要有如下两种表现方式:ide
1)方法重载(overload)。重载是指同一类中有多个同名方法,可是这些方法必须在参数列表上加以区分,要么参数个数不一样,要么在相同位置上的参数类型不一样,返回值和访问控制符能够不一样。spa
2)方法的覆盖(override)。子类能够覆盖父类的方法。父类的引用不但能够指向其实例对象,也可以指向子类的实例对象。接口的引用变量也能够指向其实现类的实例对象。设计
一、方法覆盖要求方法名,参数列表,返回值都必须相同,假如参数列表不一样就属于重载,假如返回值不一样,编译通不过!code
二、另外覆盖方法权限不能低于被覆盖方法,例如父类是public 子类就必须是public,假如是protected就通不过。对象
三、重写方法必定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如:父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,能够抛出非检查异常。blog
而程序的调用方法是在运行期才动态绑定的,就是引用变量所指向的具体实例对象的方法,而不是引用变量的类型中定义的方法。这种动态绑定实现了多态。只有运行时才可以肯定具体调用哪一个方法。所以经过方法覆盖的实例也称为运行时多态。继承
注意成员变量是没法实现多态的,成员变量的取值取决于定义变量的类型。接口
public class Father { public int i=1; public void a() { System.out.println("father a"); } public void b() { System.out.println("father b"); } }
public class Son extends Father{ public int i=5; public void a() { System.out.println("Son a"); } public void b() { System.out.println("Son b"); } public void c() { System.out.println("Son c"); } }
public static void main(String[] args) { Father father=new Son(); father.a(); father.b(); //father.c(); error System.out.println(father.i); Son son=(Son)father; //父类强制转换成子类的原则:父类型的引用指向的是哪一个子类的实例,就能转换成哪一个子类的引用 son.c(); System.out.println(son.i);
//会抛出异常 java.lang.ClassCastException: Father cannot be cast to Son
//Son son=(Son)new Father();编译器
}
输出:
Son a Son b 1 Son c 5
PS:Java动态绑定和静态绑定
这两种绑定方式是根据是否可以在编译器肯定要执行的方法来区分的。
其中只有final,static,private和构造方法是静态绑定,其余的所有是动态绑定,即在运行期才能肯定要执行的方法。
final 类的方法没法被覆盖,子类能够调用这个方法,可是都是父类的这个方法,因此在编译器就可以知道。
static是类方法,引用变量是什么类型的,调用的就是什么类型的静态方法,注意子类能够转换成父类,由于子类包含了父类的所有,而父类不能转换成子类。
Father father=new Son(); father.say(); Son son=new Son(); son.say(); father=son; father.say();
输出
father say
son say
father say
这个例子中父类和子类都有一个同名的静态方法say(),当引用变量是father类型的,那么调用的就是Father类型的,当引用变量是Son类型的,那么调用的就是Son类型的。
private是类私有的,只能在类内部调用。
构造方法不能被覆盖,能够直接绑定。
其余的方法调用都是动态绑定,相似Objective c中的isa,经过instanceof 先找到对象属于哪类类型,而后查找对象的方法表,有一样签名的就执行,不然到父类去查找。