Java 多态

Posted 守林鸟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 多态相关的知识,希望对你有一定的参考价值。

多态:一个对象有多种形态

  • 是方法的多态,和属性无关
  • 有继承关系、重写方法、父类引用 指向 子类对象
  • 静态方法不支持多态

举例,

有父类Dog,属性name="dog",普通方法say,静态方法move;

子类SDog,属性name="sdog",重写了普通方法say,重写了静态方法move,另外有自己的普通方法sd;

子类BDog,属性name="bdog",重写了普通方法say,重写了静态方法move,另外有自己的方法bd;

孙类SDog_son继承了SDog,属性name="sdog_son",重写了普通方法say,重写了静态方法move;

测试代码:

package my_test;

public class Main {
    public static void main(String[] args) {
        Dog d1;//d1是一个引用
        d1=new Dog();//d1 指向父类Dog创建的对象
        d1.say();
        d1.move();
        System.out.println(d1.name);
        System.out.println("------------------------------------------");
        d1=new SDog();//d1 指向子类SDog创建的对象,上面失去引用的对象会被回收
        d1.say();
        d1.move();
        System.out.println(d1.name);
        System.out.println("------------------------------------------");
        //d1.sd();//报错,因为Dog中没有sd()方法.The method sd() is undefined for the type Dog
        d1=new BDog();
        d1.say();
        d1.move();
        System.out.println(d1.name);
        //d1.bd();//报错,同上
        System.out.println("------------------------------------------");
        d1=new SDog_son();//d1 指向孙类SDog_son创建的对象,上面失去引用的SDog对象会被回收
        d1.say();
        d1.move();
        System.out.println(d1.name);
        System.out.println("------------------------------------------");
    }

}
class Dog {
    String name="dog";
    public void say() {
        System.out.println("dog_say");
    }
    public static void move() {
        System.out.println("dog_move");
    }
    
}

class SDog extends Dog{
    String name="sdog";
    public void say() {
        System.out.println("sdog_say");
    }
    public static void move() {
        System.out.println("sdog_move");
    }
    public void sd() {
        System.out.println("sdog自己独特的方法sd");
    }
    
}

class BDog extends Dog{
    String name="bdog";
    public void say() {
        System.out.println("bdog_say");
    }
    public static void move() {
        System.out.println("bdog_move");
    }
    public void bd() {
        System.out.println("bdog自己独特的方法bd");
    }
}

class SDog_son extends SDog{
    String name="sdog_son";
    public void say() {
        System.out.println("sdog_son_say");
    }
    public static void move() {
        System.out.println("sdog_son_move");
    }
}


class Factory{//没有报错,将用于工厂方法模式
    public Dog createdog(int id) {
        if(id==1)
            return new Dog();
        else if(id==2)
            return new SDog();
        else 
            return new BDog();
    }
}

输出:

dog_say
dog_move
dog
------------------------------------------
sdog_say
dog_move
dog
------------------------------------------
bdog_say
dog_move
dog
------------------------------------------
sdog_son_say
dog_move
dog
------------------------------------------

Dog的引用 指向 不同的子孙类对象的各种情况下:

1.调用普通方法say,输出是各自子孙类的重写方法,并且调用子类自己的方法sd()和bd()会报错。验证:继承的重写方法 支持多态

2.调用静态方法move,输出的都是父类的静态方法内容。验证:静态方法不支持多态

3.System.out.println(d1.name);输出的都是dog。验证:多态和属性无关

 

另附一些理解:

1.d1这个变量是引用,放在内存栈里。new出来的东西放在内存堆里,引用即栈指向堆。

2.编译时多态(也称静态多态,也就是调用静态方法的多态),因为编译时就加载了静态的代码块,存在静态常量池里。

3.运行时多态(也就是通常说的多态,因为大家都觉得静态方法不支持多态,实际上只是没体现出来,而我们需要解决的问题是通过运行时多态解决的,所以我们说的多态都是运行时多态),编译时不确定究竟调用哪个具体方法,一直延迟到运行时才能确定。(多态方法又被称为延迟方法的原因)。实现技术叫:动态绑定。编译时只加载静态代码,运行时才加载普通代码,当类被载入到虚拟机内部的时候,在内存中产生类的常量池叫运行时常量池。

4.静态方法可以通过类名调用,不妨理解为:d1是Dog的变量,调用静态方式是通过类调用,即d1.move()就是Dog.move()

 

以上是关于Java 多态的主要内容,如果未能解决你的问题,请参考以下文章

每个人单核苷酸多态性(SNP)形成的原因是啥?

多态性和动态铸造

Java多态——代码复用性

Java 多态

java多态/重载方法——一个疑难代码引发的讨论

Java 多态