类内多态性
在一个类对象上调用相同名称的方法,但是当参数不同时执行不同的动作
public class Test2 {public static void main ( String [] args ) {A2 a = new A2 ();a . pp ( "shitou" );}}class A2 {public void pp () {System . out . println ( "A2.pp()" );}public void pp ( Integer k ) {System . out . println ( "A2.pp(int)" );}public void pp ( Object kk ) {System . out . println ( "A2.pp(String)" );}public void pp ( int k1 , String k2 ){}public void pp ( String k1 , int k2 ){}}
方法名称相同,参数不同,和返回值类型无关
1.参数个数不同
2.参数类型不同
3.参数顺序不同。注意不同参数名称顺序不同
public class Test1 {public static void main ( String [] args ) {Fa ff = new Fa ();ff . pp ( new Integer ( 123 )); // 原则:最佳匹配原则ff . pp ( 1.234 );}}class Fa {public void pp () {System . out . println ( "Fa.pp()" );}public void pp ( Number kk ){System . out . println ( "Fa.pp(Number)" );}public void pp ( Integer kk ){System . err . println ( "Fa.pp(Integer)" );}}
不确定个数的参数
public class Test1 {public static void main(String[] args) {Fa ff = new Fa();ff.pp(); //最佳匹配原则}}class Fa {public void pp() {System.out.println("Fa.pp()");}public void pp(int... pages) {// 不确定个数的参数System.out.println("Fa.pp(int...)");}}
方法的重写和重载
要求:方法的名称一致。
方法的重写
(
覆盖
)
要求:方法的名称一致
方法的重写
(
覆盖
)
一定发生在父子类之间
public class Test4 {public static void main ( String [] args ) {F4 f = new F4 (); f . pp ( 10 );S4 s = new S4 (); s . pp ( 10 );F4 fs = new S4 (); fs . pp ( 10 );}}class F4 {public void pp ( int k ) {System . out . println ( "F4.pp(int)" );}}class S4 extends F4 {public void pp ( int k ) { // 子类中定义的同名同参数的方法覆盖了父类中的方法定义,如果需要调用父类中的方法则需要使用 super.pp(k) 进行调用System . out . println ( "S4.pp(int)" );}}
执行规则:
new
谁运行谁的方法,和声明的类型无关
方法的覆盖定义要求方法名称一致
@Override 注解可以使 IDE 工具在编译源代码时进行检查,如果有手写错误则 IDE 工具报错
方法的参数一致(个数、类型、顺序),和参数名称无关
类型一致的问题class Fa {public void eat ( Integer kk ) {System . out . println ( "Animal.eat()" );}}class Son extends Fa {@Overridepublic void eat ( Number kk ) { // 类型必须一致,即使父类类型都不可以, int 和Integer 简单类型和包装类型也不可以。这里去除 @override 注解则不会有语法错误,这里不是方法的重写,是方法的重载System . out . println ( " 就是爱老鼠 " );}}
顺序一致的问题
,
系统识别方法依靠是方法名称和参数类型列表,和方法参数的名称无关。例如这里系统识别的方法为ear(String,String)
。要识别顺序还得依靠类型的区别,例如
eat(int,double)
和
eat(double,int)
class Fa {public void eat ( String s1 , String s2 ) {System . out . println ( "Animal.eat()" );}}class Son extends Fa {@Overridepublic void eat ( String s2 , String s1 ) { // 系统不能识别变量名称System . out . println ( " 就是爱老鼠 " );}}
返回数据类型一致【面试】
(
因为如果返回类型不一致,则无法进行语法检查
,
例如父类返回
Double
,而子类返回
Integer,
调用处语法检查是按照
Double
进行检查还是按
Integer
检查?允许父
类中返回的是父类型,而子类中返回子类型,例如父类中返回的是
Number
类型,而子类中返回的
是
Integer)
class Fa {public Number eat ( double s1 , int s2 ) {System . out . println ( "Animal.eat()" );return 10. ;}}class Son extends Fa {@Overridepublic Integer eat ( double s2 , int s1 ) { // 允许子类中返回值类型是父类返回值类型的子类型System . out . println ( " 就是爱老鼠 " );return 99 ;}}
抛出异常一致,注意实际上允许子类抛出比父类更少的异常
class Fa {public Integer eat(double s1, int s2) throws Exception {System.out.println("Animal.eat()");return 10;}}class Son extends Fa {@Overridepublic Integer eat(double s2, int s1) throws IOException {System.out.println("就是爱老鼠");return 99;}}
要求子类中的方法范围
>=
父类中方法范围
静态方法覆盖和调用,用谁声明则调用谁的静态方法
只有静态方法覆盖定义父类中的静态,实际上系统不建议这种做法
//The method pp() of type Son must override or implement a supertypemethodpublic class Test1 {public static void main ( String [] args ) {// 直接使用具体类调用静态方法没有任何问题,使用哪个类就调用的是哪个类中定义的静态方法// Fa.pp();Fa...pp// Son.pp();Son...pp// 事实上静态方法也可以通过创建对象后,使用对象进行调用。声明变量的类型和具体构建的类型一致,也不会有问题// Fa ff=new Fa();// ff.pp();// 如果调用静态方法,则用谁声明调用谁的方法Fa ff = new Son ();ff . pp (); // 执行结果是 Fa...pp}}class Fa {public static void pp () {System . out . println ( "Fa...pp" );}}class Son extends Fa {public static void pp () {System . out . println ( "Son...pp" );}}
方法的重载
方法的名称相同,参数不同,和返回值类型无关。可以在一个类内或者父子类之间
调用规则:类型最佳匹配原则
class A5 {public void pp (){System . out . println ( "A5.pp()" );}public int pp (){} 语法错误,因为在系统中识别一个方法是用【方法名称 + 参数类型列表】进行,系统会将这两个pp 方法识别为同一个方法。注意:在一个类中不允许方法相同public void pp ( int k ){System . out . println ( "A5.pp(int)" );}}class B5 extends A5 {public void pp ( String k ){System . out . println ( "B5.pp(String)" );}public void pp ( String k , int k1 ){}public void pp ( int k , String k1 ){}}
多态的优点
1.消除类型之间的耦合关系
2.可替换性、可扩充性
3.接口性、灵活性、简化性
public class Test1 {public static void main(String[] args) {Fa ff = new Son();ff.pp(10);//因为在父类中声明的方法为Integer 类型,所以在执行前会自动执行装箱操作,所以调用的是从父类中继承到的pp(Integer) ,而不是最佳匹配的 pp(int)}}class Fa {protected void pp() {System.out.println("Fa.pp()");}public void pp(Integer kk){System.out.println("Fa.pp(Integer)");}}class Son extends Fa {public int pp(int k) {System.out.println("Son.pp(int)");return 10;}}
public class Test1 {public static void main(String[] args) {Fa ff = new Son();ff.pp(10);}}class Fa {protected void pp() {System.out.println("Fa.pp()");}public void pp(Integer kk){System.out.println("Fa.pp(Integer)");}}class Son extends Fa {public void pp(Integer kk){System.out.println("Son.pp(Integer)");}public int pp(int k) {System.out.println("Son.pp(int)");return 10;}}