目录
1、什么是多态
多态的定义:
Java 的多态是指在面向对象编程中,同一个类的对象在不同情况下表现出来的不同行为和状态。
- 子类可以继承父类的字段和方法,子类对象可以直接使用父类中的方法和字段(私有的不行)。
- 子类可以重写从父类继承来的方法,使得子类对象调用这个方法时表现出不同的行为。
- 可以将子类对象赋给父类类型的引用,这样就可以通过父类类型的引用调用子类中重写的方法,实现多态。
多态的目的:
多态的目的是为了提高代码的灵活性和可扩展性,使得代码更容易维护和扩展。
通俗来说,执行一段代码,Java 在运行时能根据对象类型的不同产生不同的结果。
多态的前提条件有三个:
- 子类继承父类
- 子类重写父类的方法
- 父类引用指向子类的对象
举例:
创建A类
public class A{
public String name;
public int age;
public void run(){
System.out.println("a跑的很快");
}
public void eat(String name){
System.out.println(name+"吃的很多。。。")
}
}
创建B类
public class B extends A{
public char sex;
public double height;
public void flay(){
System.out.println("b飞的更高");
}
public void run(){
System.out.println("b跑的很快");
}
}
创建测试类
public class Test{
public static void main(String[] args) {
A ab = new B();
ab.name = "hello";
ab.age = 12;
ab.eat("nihao");
ab.run(); //这里输出的是b跑的很快
}
}
内存图为:
由于ab的数据类型为A,所以ab只能使用A中的方法,由于run()方法被重写,所以ab可以使用的为下图中的绿色部分。
2、多态的转型
向上转型:子类的对象可以被父类的类型所接受(父类的引用指向子类的对象)
继续使用上面的例子:
创建A、B类
public class A{
public String name;
public int age;
public void run(){
System.out.println("a跑的很快");
}
public void eat(String name){
System.out.println(name+"吃的很多。。。")
}
}
public class B extends A{
public char sex;
public double height;
public void flay(){
System.out.println("b飞的更高");
}
public void run(){
System.out.println("b跑的很快");
}
}
创建C类
public class C{
public static void hanlder(A a){
System.out.println("c的输出");
}
}
创建测试类
public class Test{
public static void main(String[] args) {
B b = new B();
C.hanlder(b);
}
}
上面代码我们可以看到C.hanlder(b);传的参数是B类型,但是public static void hanlder(A a)输入的确是A类型,这是由于B类向上转型为A类。
3、题目详解(重点)
public class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
public class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
public class C extends B{
}
public class D extends B{
}
public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
}
}
//输出结果为
//A and A
//A and A
//A and D
//B and A
//B and A
//A and D
//B and A
//B and A
//A and D
前三行:
第1行:
System.out.println("1--" + a1.show(b)); //A and A
a1创建了一个A类对象,b创建了一个B类对象继承父类A,此时堆内存中a1对象,b对象和他的父类对象(子类对象创建需要先创建父类对象,这个父类对象是新的不同于a1创建的对象),由于a1的数据类型为A,所以只能调用A类中的方法(图中绿色部分)。b向上转型为a执行Alei中的方法show(a),打印A and A。
第2行:
System.out.println("2--" + a1.show(c)); //A and A
同1只不过c向上转型为b,b向上转型为a,打印A and A。
第3行:
System.out.println("3--" + a1.show(d)); //A and D
a1创建了一个A类对象,d创建了一个D类对象继承父类B再继承A类,此时堆内存中a1对象,d对象和b对象和新A对象(子类对象创建需要先创建父类对象,这个父类对象是新的不同于a1创建的对象),由于a1的数据类型为A,所以只能调用A类中的方法。执行show(D)方法,打印A and D。
中间三行
第4行:
System.out.println("4--" + a2.show(b)); //B and A
创建了一个B类对象继承A类,b类中对a类的方法show(A)进行了重写,所以b类对象的方法会覆盖原来的方法。a2是A类,只调A类方法(图中绿色可用),但是由于show(A)被重写,所以执行B类中的方法show(A),打印 B and A。
第5行:
System.out.println("5--" + a2.show(c)); //B and A
同4,只不过c向上转型为b,b向上转型为a。执行B类中的方法show(A),打印 B and A。
第6行:
System.out.println("6--" + a2.show(d)); //A and D
同4,执行A类中show(D)方法,打印A and D。
后三行:
第7行:
System.out.println("7--" + b.show(b)); //B and A
b创建了一个B类对象继承父类A,b的数据类型为B,执行B类中的方法,b向上转型为a执行show(A)方法,打印 B and A。(图中绿色可用)
第8行:
System.out.println("8--" + b.show(c)); // B and A
同7,只不过c向上转型为b,b向上转型为a。执行B类中的方法show(A),打印 B and A。
第9行:
System.out.println("9--" + b.show(d)); //A and D
同7,执行B类中的方法show(D),打印A and D。