java中多态的用法

思维导图:

 

1. 多态的概念

多态通俗的讲就是多种形态同一个动作,作用在不同对象上,所产生不同的形态。

例如下图:

2. 多态的实现条件

Java中,多态的实现必须满足以下几个条件:
1. 必须在继承体系下
2. 子类必须重写父类中的方法
3. 通过父类的引用调用重写方法


多态体现:在代码运行时,当传递不同对象时,会调用对应类中的方法
看以下代码:

 
public abstract class Animal {
    String name;
    int age;
    public Animal(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void eat(){
        System.out.println(name+"吃粮食");
    }
}
 
 
public class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }
 
    @Override
    public void eat() {
        System.out.println(name+"爱吃骨头");
    }
}
///
 
public class Cat extends Animal {
    public Cat(String name, int age) {
        super(name, age);
    }
 
    @Override
    public void eat() {
        System.out.println(name+"爱吃鱼");
    }
}
 
/
 
public class TestAnimal {
    //编译器在编译代码时,并不知道调用Dog还是Cat中的eat方法
    //等程序运行起来后,形参a引用的具体对象确定后,才知道调用哪个方法
    //注意:此处的形参类型必须是父类类型才可以
    public static void eat(Animal a){
        a.eat();
    }
 
    public static void main(String[] args) {
        Dog dog = new Dog("旺财",2);
        Cat cat = new Cat("糯米",1);
        eat(dog);
        eat(cat);
    }
}

3. 重写


重写(override)也称为覆盖,重写是子类对父类非静态,非private修饰,非final修饰,非构造方法等的实现过程进行重新编写返回值和形参都不能改变,核心重写。

方法重写规则:

1:子类重写父类方法时,一般必须与父类方法原型保持一致:修饰符 返回值类型 方法名(参数列表)要完全一致

2:JDK7以后,被重写的方法返回值类型可以不同,但是必须具有父子关系

3: 访问权限不能比父类父类中被重写的方法的访问权限低。

4:父类中被static private 修饰的方法,构造方法都不能被重写

5:重写的方法可以用@Override注解来显示指定

 重写和重载的区别:

 即:方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现

静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型确定具体调用哪个方法。典型代表:重载

动态绑定:也成为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时才能够确定调用哪个类的方法

 4:向上转型和向下转型

 向上转型:一个父类对象的引用指向一个子类对象的实例。
 语法格式:父类类型  对象名  =   new  子类类型();

 如:Animal animal = new Cat("小七",1);

animal是父类类型,但可以引用一个子类对象,即:可以将一个子类对象当成父类对象来引用。因此:向上转型是安全的,因为是从小范围向大范围的转换。

使用场景:1:直接赋值     2:方法传参     3:方法返回

请看如下代码:

public class TestAnimal {
    //方法传参:形参为父类类型引用,可以接受任意子类对象
    public static void eat(Animal a){
        a.eat();
    }
    //作为返回值:返回任意子类对象
    public static Animal buyAnimal(String var){
        if("狗" == var){
            return new Dog("小七",2);
        }else if("猫" == var){
            return new Cat("汤圆",1);
        }else{
            return null;
        }
    }
 
    public static void main(String[] args) {
        Animal dog = new Dog("旺财",2);   //直接赋值:子类对象赋给父类对象
        Aniaml cat = new Cat("糯米",1);
        eat(dog);
        eat(cat);
        Animal animal = buyAnimal("狗");
        animal.eat();
        animal = buyAnimal("猫");
        animal.eat();
 
    }
}

向上转型的优点:让代码实现更简单灵活
向上转型的缺陷:不能调用到子类特有的方法 

 向下转型
将一个子类对象向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转型。

public class TestAnimal {
    public static void eat(Animal a){
        a.eat();
    }
 
    public static void main(String[] args) {
        Dog dog = new Dog("旺财",2);
        Cat cat = new Cat("糯米",1);
        Animal animal = dog;
        animal.eat();
       // animal.bark();    编译器报错,Animal类中没有bark方法
        dog = (Dog)animal;
        dog.bark();
        animal = cat;
        animal.eat();
       // animal.mew();    编译器报错,Animal类中没有mew方法
        cat = (Cat)animal;
        cat.mew();
    }
}

向下转型不安全,万一转型失败,运行就会抛异常。Java中为了提高向下转型的安全性,引入了instanceof,如果该表达式为true,则可以安全转换 

public class TestAnimal {
    public static void eat(Animal a){
        a.eat();
    }
 
    public static void main(String[] args) {
        Dog dog = new Dog("旺财",2);
        Cat cat = new Cat("糯米",1);
        Animal animal = dog;
        animal.eat();
        animal = cat;
        animal.eat();
        if(animal instanceof Dog){
            dog = (Dog)animal;
            dog.bark();
        }
        if(animal instanceof Cat){
            cat = (Cat)animal;
            cat.mew();
        }
    }
}

 多态的优点
 1:能够降低代码的“圈复杂度”,避免使用大量的if-else
假如我们现在要打印多个形状而不是一个形状

public static void drawShapes(){
        Ret ret = new Rect();
        Cycle cycle = new Cycle();
        Flower flower = new Flower();
        String[] shapes = {"cycle","ret","flower","cycle","flower"};
        for(String shape : shapes){
            if(shape.equals("cycle")){
                cycle.draw();
            }
            if(shape.equals("ret")){
                ret.draw();
            }
            if(shape.equals("flower")){
                flower.draw();
            }
        }
    }

 如果使用多态,代码更简单:请看如下代码:

 public static void drawShapes(){
        Shape[] shapes = {new Cycle(),new Rect(),new Cycle(),new Flower()};
        for(Shape shape : shapes){
            shape.draw;
        }
    }

2. 可扩展能力强
增加一种新的形状,使用多态的方式代码改动成本低

class Tringle extends Shape{
    @Override
    public void draw(){
        System.out.println("三角形");
    }
}

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 多态性是指同一个方法调用会根据对象类型的不同而具有不同的行为。多态性主要有两种表现形式:覆盖和重载。 覆盖(Override)是指在子类定义一个与父类同名、同参数列表的方法,这个子类的方法会覆盖父类的方法。当父类引用指向子类对象时,调用该方法时会优先调用子类的方法。 重载(Overload)是指在一个类定义多个方法,它们具有相同的方法名但参数列表不同。编译器会根据参数列表的不同来选择相应的方法。 下面是一个使用多态的例子: ``` class Animal { public void makeSound() { System.out.println("The animal makes a sound"); } } class Dog extends Animal { public void makeSound() { System.out.println("The dog barks"); } } class Cat extends Animal { public void makeSound() { System.out.println("The cat meows"); } } public class Main { public static void main(String[] args) { Animal a = new Animal(); // Animal reference and object Animal b = new Dog(); // Animal reference but Dog object Animal c = new Cat(); // Animal reference but Cat object a.makeSound(); // runs the method in Animal class b.makeSound(); // runs the method in Dog class c.makeSound(); // runs the method in Cat class } } ``` 输出结果为: ``` The animal makes a sound The dog barks The cat meows ``` 在这个例子,Animal 是一个父类,Dog 和 Cat 是它的子类。Animal 类的 makeSound() 方法被子类重写了,当父类引用指向子类对象时,调用该方法时会优先调用子类的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值