Java中重写、重载与运行、编译时的多态

1、多态

1.1、定义:

同一事物表现出不同事物的能力,即向不同对象发送同一消息,不同的对象在接收时会产生不同的行为(重载实现编译时多态,虚函数实现运行时多态)。
多态性分为编译时的多态性和运行时的多态性。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现运行时多态需要做以下两件事情:
方法重写(子类继承父类并重写父类中已有的或抽象的方法)。
用父类型引用变量引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为。

1.2、功能

多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。

2、编译时多态

方法重载就是在同一个类中,出现了多个同名的方法,他们的参数列表(方法签名)不同 (参数列表的个数不同,参数列表的数据类型不同,参数列表的顺序不同)。方法重载都是编译时多态。根据实际参数的数据类型、个数和次序,Java在编译时能够确定执行重载方法。

public class chongzaixie {
    public static void main(String[] args) {
        Person p=new Person(); // 对象引用本类实例
        Man m=new Man();// 对象引用本类实例
        System.out.println(p.toString()); // 编译时多态,执行Person类的toString
        System.out.println(m.toString()); // 编译时多态,执行Man类的toString
    }
}

class Person{
    public String toString(){
        String name="Person";
        return name;
    }
}

class Man extends Person{
    public String toString(){
        String name="Man";
        return name;
    }
}

3、运行时多态

当父类引用指向子类对象时(重写)。

3.1、父类引用子类实例

父类只能执行那些在父类中声明、被子类覆盖了的子类方法,而不能执行子类新增加的成员方法。在编译时期,首先会去查看父类里面有没有这个方法,如果没有的话向上继续查找,直到找到Object类如果还没有的话就报错,如果有的话,到运行阶段,再去看一下子类中有没有覆盖该方法,如果覆盖了,则执行子类覆盖的方法。如果没有则执行父类中原本的方法。

public class chongzaixie {
    public static void main(String[] args) {
        Person n=new Man();  // 运行时多态,如果Man中有toString,则运行Man中的,没有则运行Person中的
        System.out.println(n.toString());
    }
}

class Person{
    public String toString(){
        String name="Person";
        return name;
    }
}

class Man extends Person{
    public String toString(){
        String name="Man";
        return name;
    }
}

3.2、不能编译父类没有而子类有的方法

当子类和父类有相同属性时,父类还是会执行自己所拥有的属性,若父类中没有的属性子类中有,当父类对象指向子类引用时(向上转型),在编译时期就会报错。

3.3、子类隐藏父类的属性

例子中子类Man隐藏父类Person的属性,而 Person p = new Man() 表示“先声明一个Person类的对象p,然后用Man类对 p进行实例化”,即引用类型为Person类,实际代表的是Man类。因此,访问的是Person的属性及静态方法。
对于static方法还是会执行父类中的方法,这是由于在运行时,虚拟机已经认定static方法属于哪个类。“重写”只能适用于实例方法,不能用于静态方法。**对于静态方法,只能隐藏,重载,继承。**子类会将父类静态方法的隐藏(hide),但子类的静态方法完全体现不了多态,就像子类属性隐藏父类属性一样,在利用引用访问对象的属性或静态方法时,是引用类型决定了实际上访问的是哪个属性,而非当前引用实际代表的是哪个类。因此,子类静态方法不能覆盖父类的静态方法。

public class chongzaixie {
    public static void main(String[] args) {
        Person q=new Man();
        System.out.println(((Man)q).getName()); //返回Man
    }
}

class Person{
    public String toString(){
        String name="Person";
        return name;
    }
}

class Man extends Person{
    public String toString(){
        String name="Man";
        return name;
    }
    public String getName(){
        String name="Man";
        return name;
    }
}

你可能感兴趣的:(java基础,java,jvm,开发语言)