Java面向对象(OOP)--面向对象三大特性之一:多态(多态方法绑定instanceof和类型转换(重写重载和多态的关系))

Posted Z && Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面向对象(OOP)--面向对象三大特性之一:多态(多态方法绑定instanceof和类型转换(重写重载和多态的关系))相关的知识,希望对你有一定的参考价值。

1. 多态


1.1 认识多态

  • 多态性是OOP中的一个重要特性,主要是用来实现动态联编的,换句话说,就是程序的最终状态只有在执行过程中才被决定而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性和扩展性。
  • 多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法,从而实现更加灵活的编程,提高系统的可扩展性。
  • 允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
  • 相同类域的不同对象,调用相同的方法,执行结果是不同的

一个对象的实际类型是确定的

可以指向对象的引用的类型有很多

注:一个对象的实际类型是确定,但是可以指向这个对象的引用的类型,却是可以是这对象实际类型的任意父类型。


1.2 重写、重载和多态的关系


1.3 多态的注意事项

  1. 多态是方法的多态,属性没有多态性。
  2. 编写程序时,如果想调用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。但是如果两个没有关联的类进行强制转换,会报:ClassCastException。 比如:本来是狗,我把它转成猫。就会报这个异常。
  3. 多态的存在要有3个必要条件:要有继承,要有方法重写,父类引用指向子类对象

1.4 多态存在的条件

  1. 有继承关系
  2. 子类重写父类方法
  3. 父类引用指向子类对象

补充一下第二点:

既然多态存在必须要有“子类重写父类方法”这一条件,那么以下三种类型的方法是没有办法表现出多态特性的(因为不能被重写):

  1. static方法,因为被static修饰的方法是属于类的,而不是属于实例的
  2. final方法,因为被final修饰的方法无法被子类重写
  3. private方法和protected方法,前者是因为被private修饰的方法对子类不可见,后者是因为尽管被protected修饰的方法可以被子类见到,也可以被子类重写,但是它是无法被外部所引用的,一个不能被外部引用的方法,怎么能谈多态呢。

1.5 方法绑定(method binding)

执行调用方法时,系统根据相关信息,能够执行内存地址中代表该方法的代码。分为静态绑定和动态绑定。


1.5.1 静态绑定

在编译期完成,可以提高代码执行速度。


1.5.2 动态绑定

通过对象调用的方法,采用动态绑定机制。这虽然让我们编程灵活,但是降低了代码的执行速度。这也是JAVA比C/C++速度慢的主要因素之一。JAVA中除了final方法、static方法,所有方法都是JVM在运行期才进行动态绑定的。


1.6 instanceof和类型转换


1.6.1 instanceof

对于: System.out.println(x instanceof Y)

  • 该代码能否编译通过,主要是看声明变量x的类型和Y是否存在子父类的关系.有"子父类关"系就编译通过, 没有子父类关系就是编译报错.
  • 输出结果是true还是false,主要是看变量x所指向的对象实际类型是不是Y类型的"子类型".

示例:

public class Test {
    public static void main(String[] args) {
        Object o = new Student();
        System.out.println(o instanceof Student);//true
        System.out.println(o instanceof Person);//true
        System.out.println(o instanceof Object);//true
        System.out.println(o instanceof Teacher);//false
        System.out.println(o instanceof String);//false
        System.out.println();

        Person person = new Student();
        System.out.println(person instanceof Student);//true
        System.out.println(person instanceof Person);//true
        System.out.println(person instanceof Object);//true
        System.out.println(person instanceof Teacher);//false
        //编译报错
        System.out.println(person instanceof String);
    }
}

class Person {
    public void run() {
    }
}

class Student extends Person {
}

class Teacher extends Person {
}

1.6.2 类型转换

现在有3个类:

class Person {
    public void run() {
    }
}

class Student extends Person {
    public void go() {
    }
}

class Teacher extends Person {
}

为什么要类型转换

【类型转换中的问题】

public class Test {
    public static void main(String[] args) {
        //编译通过 运行没问题
        Object o1 = new Student();
        Person p = (Person) o1;
        //编译通过 运行没问题
        Object o2 = new Student();
        Student s1 = (Student) o2;
        //编译通过,运行报错
        Object o3 = new Teacher();
        Student s2 = (Student) o3;
    }
}

class Person {
    public void run() {
    }
}

class Student extends Person {
    public void go() {
    }
}

class Teacher extends Person {
}

对于: X x = (X)o;
运行是否报错,主要是变量o所指向的对象实现类型,是不是X类型的子类型,如果不是则运行就会报错。


1.7 【总结】

  • 父类引用可以指向子类对象,子类引用不能指向父类对象。
  • 把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转型。如Father father = new Son();
  • 把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转型。如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即 Son son = (Son) new Father();其中new Father()前面的(Son)必须添加,进行强制转换。
  • upcasting (向上转型)会丢失子类特有的方法,但是子类overriding 父类的方法,子类方法有效
  • 向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。体现了JAVA的抽象编程思想。


以上是关于Java面向对象(OOP)--面向对象三大特性之一:多态(多态方法绑定instanceof和类型转换(重写重载和多态的关系))的主要内容,如果未能解决你的问题,请参考以下文章

Java面向对象(OOP)--面向对象三大特性之一: 继承(继承Object类Super关键字方法重写)

面向对象编程基本部分——java三大特性详解

OOP的三大特性是啥

java第五章:面向对象(oop)之三大特性

java第五章:面向对象(oop)三大特性之多态

JAVA面向对象三大特性总结