Java中的多态(Polymorphism)是面向对象编程的三大特性之一,另外两个是封装(Encapsulation)和继承(Inheritance)。多态允许你使用一个接口来表示多种数据类型。
在Java中,多态主要体现在以下几个方面:
Overloading+Overriding+Upcasting+Downcasting
方法的重载(Overloading):在同一个class中,method名相同,但参数列表(参数类型、个数或顺序)不同的多个方法。
public class Example {
void show(int x) {
System.out.println("整数:" + x);
}
void show(double x) {
System.out.println("双精度:" + x);
}
}
方法的重写(Overriding):child class可以覆盖parent class中的method,即child class和parent class有相同名称、相同参数列表和相同return类型的method。当子类object调用这个method时,会按照child class中的method执行,而不是parent class中的同名method执行。
class Parent {
void show() {
System.out.println("Parent's show()");
}
}
class Child extends Parent {
@Override
void show() {
System.out.println("Child's show()");
}
}
对象的向上转型(Upcasting):(只应用于non-static method)定义好的parent类型的变量p,虽然指向了child class,但依旧只能调用父类中独有的non-static method,而不能调用child class独有的method。
Parent p = new Child();
p.show(); // 调用Parent类的show()方法
(Child(p)).childplay();//调用子类独有的childplay method,只能先强制转换成子类(Child(p)),然后再调用
对象的向下转型(Downcasting):将parent class类型的变量转换为子类类型child class。这需要明确地进行类型转换,并且只有在运行时该对象确实是子类的实例时,转换才会成功。引用类型之间的类型转换,关键字instanceof(参见下面举例)
if (p instanceof Child) { //如果 object p 是Child class的子类,那么括号内为true
Child c = (Child) p;
c.show(); // 调用Child类的show()方法
//其实上面两句可以合写成一句((Child)p).show();
}
多态的主要好处是提高代码的灵活性和可扩展性。例如,你可以定义一个方法,该方法接受一个父类类型的参数,然后在运行时传递任何子类的对象。这样,你可以在不知道具体子类类型的情况下调用该方法,但方法内部会根据对象的实际类型执行相应的操作。这种特性在设计模式(如工厂模式、策略模式等)中经常被用到。
备注:不可重写override的几种情况
动态编译:类型 可扩展性
即同一method可以根据object的不同而采用多种不同的行为方式
一个对象的实际类型是确定的,但可以指向对象的引用类型有很多
多态存在的条件
注意:多态是方法的多态,属性没有多态性
//一个对象的实际类型是确定的
// Student s1
// Person s2
//但是其指向的引用类型就不确定了
Student s1= new Student();
Person s2= new Student();
举例
package oop;
import oop.Demo06.Person;
import oop.Demo06.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
// s1 Student();
// s2 Person();
//实际类型是Student()但是其指向的引用类型就不确定了
//Student能调用的方法都是自己的或者继承父类的
Student s1= new Student();
Person s2= new Student();//父类的引用指向子类的类型
//Person父类,可以指向子类,但是不能调用子类独有的方法
Object s3= new Student();
// Object父类,可以指向子类,但是不能调用子类独有的方法,
s1.run();//
s2.run(); //这里父类和子类都有run method,父类触发method run,最后运行的子类student run,属于同名method override
//如果子类重写了父类的同名方法,那么执行子类的方法就好
//s3.run(); //object父类里面没有run method,调用run失败
s1.eat();
//s2.eat(); 没法使用,因为父类person里面并没有eat这个方法
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
((Student)s2).eat();//如果实在想用,强制类型转换成Student类型后再用
}
}
package oop.Demo06;
public class Student extends Person{
public void run(){
System.out.println("student is running");
}
public void eat(){
System.out.println("student is eating");
}
}
package oop.Demo06;
public class Person {
public void run(){
System.out.println("person run");
}
}
运行结果:
student is running
student is running
student is eating
student is eating
多态注意事项:
下面三个无法override,比如
多态是method的多态 属性没有多态性
instanceof是什么:
object_a instanceof class_A
是 Java 中是Java中的二元运算符,用于测试一个object_a是否是指定class_A的实例或其子类child class的实例。它返回一个布尔值,如果对象是给定类型的实例,则返回 true,否则返回 false。
instanceof作用: 判断object是不是class的子类
instanceof写法:左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。
举例
package oop;
import oop.Demo06.Person;
import oop.Demo06.Student;
import oop.Demo06.Teacher;
public class Application {
Object k = new Student();
//当前k定义为属于Object类,并且可执行student()结构的一个对象,即就是符合student类的对象。
//Object > Person > Student
System.out.println(k instanceof Student);//k和Student类有父子关系吗?是的。
System.out.println(k instanceof Person);//k和Person类有父子关系吗?是的。
System.out.println(k instanceof Object);//k和Object类有父子关系吗?是的。
System.out.println(k instanceof Teacher);//k和Teacher类有父子关系吗?没有。
System.out.println(k instanceof String);//k和String类有父子关系吗?没有。
System.out.println("=================================>");
Person y = new Student();
//当前k定义为Person类,符合student()结构的对象,即就是符合student类的对象。
//Object > Person > Student
System.out.println(y instanceof Student);//k和Student类有父子关系吗?是的。
System.out.println(y instanceof Person);//k和Person类有父子关系吗?是的。
System.out.println(y instanceof Object);//k和Object类有父子关系吗?是的。
System.out.println(y instanceof Teacher);//k和Teacher类有父子关系吗?没有,teacher和Student属于平级。
//System.out.println(y instanceof String);//k和String类有父子关系吗?没有。
}
}
package oop.Demo06;
public class Person {
public void run(){
System.out.println("person run");
}
}
package oop.Demo06;
public class Teacher extends Person{
}
package oop.Demo06;
public class Student extends Person{
public void run(){
System.out.println("student is running");
}
public void eat(){
System.out.println("student is eating");
}
}
运行结果
true
true
true
false
false
=================================>
true
true
true
false