多态性依赖于方法覆写。
class A {
public void print() {
System.out.println("A中的方法");
}
}
class B extends A {
public void print() {
System.out.println("覆写的方法");
}
}
public class Demo {
public static void main(String[] args) {
B b = new B();
b.print(); // 覆写的方法
}
}
1、多态性分为两种:
(1)方法的多态性
|- 方法重载:同一个方法名,根据传入的参数类型或个数的不同,执行不同方法体;
|- 方法覆写:同一个方法,根据对象所属的子类不同,执行不同方法体。
(2)对象的多态性:指发生在具有继承关系的类中,父类与子类的转换。
|- 向上转型(自动完成):父类 父类对象 = 子类实例化;
|- 向下转型(强制完成):子类 子类对象 = (父类)父类实例化;
范例:向上转型
public class Demo {
public static void main(String[] args) {
A a = new B();
a.print(); // 覆写的方法
}
}
范例:向下转型
public class Demo {
public static void main(String[] args) {
B b = (B) new A(); // 向下转型
b.print(); // 覆写的方法
}
}
2、向上转型:由于子类对象都可以自动向上转型,所以可应用于参数的统一。
class A {
public void print() {
System.out.println("A中的方法");
}
}
class B extends A {
public void print() {
System.out.println("B覆写的方法");
}
}
class C extends A {
public void print() {
System.out.println("C覆写的方法");
}
}
public class Demo {
public static void main(String[] args) {
A a1 = new B(); // 向上转型
A a2 = new C(); // 向上转型
a1.print(); // B覆写的方法
a2.print(); // C覆写的方法
}
}
a1,a2参数统一后,还可以调用子类覆写的方法,即同一个方法针对不同子类可以有不同实现。
3、向下转型:父类发生向上转型后,不能调用子类中自定义的方法。因此当父类要调用子类自定义方法时,需要进行向下转型,将父类对象变为子类对象。
class A {
}
class B extends A {
public void fun() {
System.out.println("自定义方法");
}
}
public class Demo {
public static void main(String[] args) {
A a = new B(); // 向上转型
a.fun(); // 报错,无法调用B自定义方法
}
}
向下转型后,可以调用子类自定义的方法:
class A {
}
class B extends A {
public void fun() {
System.out.println("自定义方法");
}
}
public class Demo {
public static void main(String[] args) {
A a = new B(); // 向上转型
B b = (B) a; // 向下转型
b.fun();
}
}
问题:上述代码中不适用向下转型,直接实例化子类对象就可以直接调用fun(),为什么还要转型?
答:数据的操作分为两步:设置数据(最需要进行参数统一)和取出数据。
public class Demo {
public static void main(String[] args) {
fun(new B()); // 向上转型
}
public static void fun(A a){ // 统一参数
B b = (B) a; // 向下转型
b.fun(); // 调用子类自定义方法
}
}
5、个性化操作在开发中尽量少出现,因为对象的强制转型容易带来安全隐患。
class A {
public void print() {
System.out.println("A.print()");
}
}
class B extends A {
public void print() {
System.out.println("B.print()");
}
}
public class Demo {
public static void main(String[] args) {
A a = new A();
B b = (B) a;
b.print();
}
}
上述代码会报错,Exception in thread "main" java.lang.ClassCastException: A cannot be cast to B at ExDemo.main(ExDemo.java:15)
,表示类转换异常,指的是两个没有关系的类对象强制进行向下转型时发生的异常,因此向下转型存在风险。
为保证转型的安全性,Java提供关键字instanceof
,其返回结果为boolean:对象 instanceof 类
如果某个对象是某个类的实例,则会返回true,反之返回false。
class A {
public void print() {
System.out.println("A.print()");
}
}
class B extends A {
public void print() {
System.out.println("B.print()");
}
}
public class Demo {
public static void main(String[] args) {
A a = new B();
System.out.println(a instanceof A); // true
System.out.println(a instanceof B); // true
if (a instanceof B) {
B b = (B) a;
b.print(); // B.print()
}
}
}
向下转型前应先进行对象的向上转型,建立关系后才能进行向下转型。
总结:
(1)大多数情况只使用向上转型,使得参数统一,便于程序设计;子类尽量覆写方法,而不是自定义方法;
(2)极少情况使用向下转型调用子类的自定义方法,或者不转型。