Java基本概念:多态
一、简介
描述:
- 多态性是面向对象编程中的一个重要特性,主要是用来实现动态联编的。换句话说,就是程序的最终状态只有在执行过程中才被决定,而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性和扩展性。
- 多态允许相同类域的不同对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
- 多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法,从而实现更加灵活的编程,提高系统的可扩展性。
- 如果对象的编译时类型和运行时类型不一致,就会造成多态。
存在条件:
- 类之间有继承关系。
- 子类重写父类方法。
- 父类引用指向子类对象。
注意:
- 多态是方法的多态,属性没有多态性。
- 一个对象的实际类型是确定的,但是可以指向这个对象的引用的类型,却是可以是这对象实际类型的任意父类型。
- 子类继承父类,调用方法,如果该方法在子类中没有重写,那么就是调用的是子类继承父类的方法,如果重写了,那么调用的就是重写之后的方法。
- 'protected'修饰的父类方法可以被子类见到,也可以被子类重写,但是它是无法被外部所引用的,所以没有多态性。
- 通过一个变量调用其引用的对象的一个方法,编译器是否能让其编译通过,主要是看该变量类型的类中有没有定义该方法,如果有则编译通过,如果没有则编译报错。而不是看这个变量所引用的对象中有没有该方法。
- Java中的方法调用,是运行时动态和对象绑定的,不到运行的时候,是不知道到底哪个方法被调用的。
- 编写程序时,如果想调用运行时类型的方法,只能进行类型转换,不然通不过编译器的检查。但是如果两个没有关联的类进行强制转换,会报类型转换异常:ClassCastException。
示例:
public class Test {
public static void main(String[] args) {
/* 编译看左,运行看右 */
Student student = new Student();
/* 变量person是可以指向Person类型或其子类型的对象,所以可以指向Student类型对象 */
Person person = new Student();
/* 变量student能调用的方法是Student类中有的方法(包括继承过来的) */
student.say();//Student
/* 变量person能调用的方法是Person类中有的方法 */
person.say();//Student
}
}
class Person {
public void say() {
System.out.println("Person");
}
}
class Student extends Person {
public void say() {
System.out.println("Student");
}
}
二、重写、重载、多态的关系
- 重载是编译时多态
- 调用重载的方法,在编译期间就要确定调用的方法是谁,如果不能确定则编译报错 。
- 重写是运行时多态
- 调用重写的方法,在运行期间才能确定这个方法到底是哪个对象中的。
- 重写方法所属取决于调用方法的引用,在运行期间所指向的对象是谁,那么调用的就是该对象中的方法。
三、方法绑定
- 程序执行调用方法时,系统根据相关信息,能够执行内存地址中代表该方法的代码。
- 根据绑定方法的代码的时机不同,分为静态绑定和动态绑定。
静态绑定:
- 在编译期完成,可以提高代码执行速度。
动态绑定:
- 通过对象调用的方法,采用动态绑定机制。
- 这虽然让我们编程灵活,但是降低了代码的执行速度。
- Java所有方法都是JVM在运行期才进行动态绑定的。
四、'instanceof'关键字
描述:
- 'instanceof'是Java的一个二元操作符。
- 'instanceof'是Java的保留关键字。
- 'instanceof'的作用是测试它左边的对象是否是它右边的类的实例,返回一个布尔值。
注意:
- 'instanceof'左边的引用的类型与右边的类之间,必须有父子关系或子父关系,否则编译会报错。
- 'instanceof'的布尔值结果,根据左边的引用的对象类型是否为右边的类的子类型。
示例:
public class Test {
public static void main(String[] args) {
Object object = new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
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
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
}
}
class Person {
}
class Student extends Person {
}
class Teacher extends Person {
}
五、类型转换
描述:
- 由于多态的关系,父类引用可以指向子类对象,子类引用不能指向父类对象。当我们想要调用子类中的方法,而对象的引用类型是其父类时,就需要将该引用类型进行强制类型转换。
- 把子类对象直接赋给父类引用叫向上转型,向上转型不用进行强制类型转换。
- 把指向子类对象的父类引用赋给子类引用叫向下转型,需要进行强制类型转换。
- 向上转型会丢失子类特有的方法,但是子类若重写了父类的方法,重写的子类方法仍有效。
- 向上转型可以减少重复代码,体现了抽象编程的思想。父类引用作为形式参数,调有时用子类引用作为实际参数,就是利用了向上转型。
强制类型转换语法:
(targetType) object
示例:
public class Test {
public static void main(String[] args) {
Person person1 = new Student();
Student student1 = (Student) person1;
student1.go();//studentGo
student1.run();//studentRun
person1.run();//studentRun
Object object1 = new Student();
Person person2 = (Person) object1;
person2.run();//studentRun
/*
因为object2引用的对象类型不是Student的子类型,所以以下代码会出现运行时异常:ClassCastException
Object object2 = new Teacher();
Student student2 = (Student) object2;
*/
}
}
class Person {
public void run() {
System.out.println("personRun");
}
}
class Student extends Person {
public void run() {
System.out.println("studentRun");
}
public void go() {
System.out.println("studentGo");
}
}
class Teacher extends Person {
}
赞 (0)