Java中多态性指允许不同类的对象对同一消息做出响应。即不同子类的对象调用同一个方法,采取的执行过程和得到的结果不同。
(1)编译时多态:主要是方法的重载,通过参数列表的不同来区分不同的方法。 (2)运行时多态:主要有继承多态和接口多态,在运行期间判断引用对象的实际类型,根据实际类型判断并调用相应的属性和方法。用于子类继承父类或者类实现接口时,父类引用指向子类对象。
多态的主要作用适用于消除类型之间的耦合关系。
(1)继承。 (2)重写覆盖。 (3)对象向上造型,即父类引用指向子类对象。
(1)创建父类。 (2)创建子类,并重写父类的方法。 (3)父类引用作为参数,实际调用传递的是子类的对象,不同的子类对象,执行过程和结果是不同的。
(1)创建接口。 (2)创建实现类,并实现接口抽象的方法。 (3)接口引用作为参数,实际调用传递的是实现类的对象,不同的实现类对象,执行过程和结果是不同的。
向上转型(自动转换)是将父类引用指向子类对象。 此时的属性的值都是父类中定义的属性的值(无论子类中是否有同名的属性)。如果子类中重写了父类的方法,此时调用的是子类的方法。如果子类中没有重写父类的方法,此时调用的是父类的方法。
// 父类引用指向子类对象(向上转型[自动转换]) Animal animal = new Pig(); System.out.println(animal.name); //animal animal.show1();//Pig show1 animal.show2();//Animal show2
向下转型(强制转换)是将子类引用指向父类对象。 向下转型不能硬转换,运行会出现ClassCastException异常
Animal a = new Animal(); Pig pigAnimal = (Pig)a;并不是所有的对象都可以向下转型,只有当这个对象原本就是子类对象通过向上转型得到的时候,向下转型才能成功。
Aimal animal = new Pig(); Pig pig = (Pig)animal; System.out.println(pig.name);//pig pig.show1();//Pig show1 pig.show2();//Animal show2 pig.show3();//Pig show3
抽象类和抽象方法是在软件开发过程中都是设计层面的概念
抽象类是用abstract修饰的类。抽象类可继承抽象类,也可以实现多接口。
抽象类可以有普通成员变量和普通成员方法,能被子类继承。
抽象类是抽象方法的容器,如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。抽象类中可以包含有非抽象的方法,甚至可以没有抽象方法。
抽象类可以有构造函数,但是不能直接创建抽象类的实例对象。
抽象类不可以直接实例化,只可以用来继承作为其他类的父类存在。如果抽象类的子类不是抽象类,就必须实现其父类所有的抽象方法。如果抽象类的子类是抽象类,可以不用实现其父类的抽象方法,但是只能用于继承,不能实例化。
/** * 抽象类 Shape * @author Administrator * */ public abstract class Shape { }
抽象方法是用abstract修饰的方法,抽象方法没有方法体,只有方法声明。抽象方法实际上就是由抽象类强制要求其子类(不是抽象类)必须实现的方法原型。 如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。
/** * 抽象类 Shape * @author Administrator * */ public abstract class Shape { /** * 抽象方法 getArea * 没有方法体,只有方法声明 */ public abstract void getArea(); }
接口是设计层面的概念。
Java中接口是一个比抽象类更加抽象的概念,由于只声明行为,因此在接口中的方法均是抽象的。但是在JDK1.8之后,出现了可以提供实现的默认方法。如果一个类实现了接口,那么该子类必须实现父接口的所有方法。接口中方法的默认访问修饰符为public。
由于接口本身就是抽象的,所以接口可以使用abstractr关键字修饰。
公开静态常量:在接口中值只存在公开静态常量(即使没有使用 public、static、final 关键字修饰,Java 也会默认确定其性质为公开静态常量),接口中的公开静态常量可以被子接口继承,也可以在接口的实现类中使用。
① 公开抽象方法:使用 public、abstract 关键字修饰(即使没有使用 public、abstract 关键字修饰,Java 也会默认确定其性质为公开抽象方法),接口中的公开抽象方法可以被子接口继承。在类实现接口时,需要实现该接口中的所有抽象方法。 ② 默认方法:使用 default 关键字修饰,是普通的方法。默认方法的访问权限修饰符为public, 默认方法的public是可以不用写的。是在JDK1.8之后出现,默认方法提供方法的具体实现。接口中的默认方法可以被实现类和子接口继承。
public interface IFly { // 公开静态常量 public static final int i = 10; // 公开抽象方法 public abstract void fly(); // 默认方法(jdk1.8之后出现) default void show() { int s = 12; System.out.println("默认方法"+s); } }③ 静态方法:接口中是可以定义静态方法的,静态方法必须要有实现,且这个静态方法只能用public修饰。接口中的静态方法是不会被实现类继承和子接口继承。
public interface IFly { // 公开静态常量 public static final int i = 10; // 公开抽象方法 public abstract void fly(); // 默认方法(jdk1.8之后出现) default void show() { int s = 12; System.out.println("默认方法"+s); } // 公开静态方法 public static void test(){ System.out.println("static method"); }; }
(1)类与接口之间为多实现,类通过使用 implements 关键字实现接口,如果有多个接口,使用逗号隔开。
(2)接口与接口之间支持多继承。接口可以继承多个接口,接口继承接口依然使用关键字extends(不要错用成 implements),extends关键字后面可以是一个列表。
public interface IFly extends IEat,IEat2 { public static final int i = 10; public abstract void fly(); default void show() { int s = 12; System.out.println("默认方法"+s); } }(3)一个类可以同时继承一个父类并实现若干接口。
public class Bird extends Animal implements IEat, IFly { @Override public void fly() { System.out.println("小鸟在飞"); } @Override public void eat() { System.out.println("小鸟在吃"); } }
抽象类的成员变量没有限制,接口的成员变量都是公开静态常量。 抽象类的构造方法可有可无,接口没有构造方法。 抽象类的成员方法有抽象方法和普通方法,接口的成员方法有公开抽象方法、默认方法和静态方法。 抽象类和类之间的关系是单继承,抽象类与抽象类之间的关系是单继承,接口与类之间的关系是多实现,接口与接口之间的关系是多继承。