Java多态详解

一、多态的理解:

去完成某个行为,当不同的对象去完成时会产生出不同的状态。

例如:当完成吃这个行为时,小猫小狗吃的就不一样,小猫吃猫粮,小狗吃狗粮

二、多态的实现:

在实现多态之前,先要了解向上转型和方法重写

1、向上转型

就是创建对象时将子类给到父类,但是这个对象只能引用父类里的成员,不能引用子类里的

class Animal{
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println(this.name + "正在吃");
    }
}
class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }

    public void bark(){
        System.out.println(this.name + "汪汪叫");
    }
}
class Bird extends Animal{
    public Bird(String name, int age) {
        super(name, age);
    }

    public void zhi(){
        System.out.println(this.name + "吱吱叫");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog("小黄",12);
        //向上转型,将子类给到父类
        animal.eat();
        //animal.bark();错误,因为Animal里面没有
        //只能访问自己特有的
    }
}

结果

 

2、重写

重写要求:方法名相同,方法的参数列表相同(个数、顺序、类型),方法的返回值相同

例如:当我们在Dog类里重写了一个吃的方法时

class Animal{
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println(this.name + "正在吃");
    }
}
class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat(){
        System.out.println(this.name + "正在吃狗粮");
    }
    public void bark(){
        System.out.println(this.name + "汪汪叫");
    }
}
class Bird extends Animal{
    public Bird(String name, int age) {
        super(name, age);
    }

    public void zhi(){
        System.out.println(this.name + "吱吱叫");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog("小黄",12);
        animal.eat(); 
    }
}

 结果:

却发现访问的是Dog里的eat

上述情况就叫动态绑定

发生前提:

1、需要发生向上转型

2、通过父类引用调用重写的方法

也有静态绑定:在编译的时候就确定调用了哪个方法

例如:  public  int add(int,int)    public  int add(int,int,int) 当调用add(1,2,3),就知道调用的是int add(int,int,int)这个方法

@Override这个注解是重写的意思,作用帮助检查,如果不满足重写要求就会报错

点左边的o⬆就能找到被重写的方法

注意Overload是重载

3、重写总结:

1、静态方法不能被重写

2、被private修饰的放法不能被重写

3、被final修饰的方法(密封方法)不能被重写

4、如果方法被重写,子类的权限要大于等于父类的权限

5、方法返回值可以不同:前提是返回值构成父子关系

public Animal eat(){}

public Dog eat(){}

两者构成了协变类型

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

动态绑定在编译的时候确实是Animal的eat方法,但是运行的时候,调用了Dog的eat(),此时我们就把他叫动态绑定。

4、发生向上转型的三种情况

(1)、直接赋值

(2)、方法传参

(3)、方法返回

public class Test {

    public static void func(Animal animal1){
        
    }

    public static Animal func2(){
        return new Dog("小黄",12);
    }

    public static void main(String[] args) {

        Animal animal = new Dog("小黄",12);//直接赋值
        //向上转型,将子类给到父类

        func(new Dog("小黄",12));//方法传参

        func2();//返回值
   }
}

向上转型的优点:让代码实现更简单灵活

向上转型的缺点:不能调用到子类特有的方法

三、多态的概念

当animal引用的对象不一样,调用eat方法表现的行为不一样,此时就叫多态

也就是当同一类引用的对象类不一样时,调用相同的方法但得到的结果不一样,就是多态

举例:

class Shape{
    public void draw(){
        System.out.println("画图形");
    }
}
class Rect extends Shape{
    @Override
    public void draw() {
        System.out.println("画一个矩形");
    }
}
class Cycle extends Shape{
    @Override
    public void draw() {
        System.out.println("画一个圆");
    }
}
class Triangle extends Shape{
    @Override
    public void draw() {
        System.out.println("画一个三角形");
    }
}
public class test {
    public static void drawMap(Shape shape){
        shape.draw();
    }
    public static void main(String[] args) {
        drawMap(new Rect());
        drawMap(new Cycle());
        drawMap(new Triangle());
    }
}

使用多态的好处

1、降低代码的“圈复杂度”,避免使用大量的if else

public class test {

    public static void drawMap2(){
        Rect rect = new Rect();
        Cycle cycle = new Cycle();
        Triangle triangle = new Triangle();
        
        Shape[] shapes = {cycle, rect, cycle, rect, triangle};
        for(Shape shape:shapes){
            shape.draw();
        }
    }
    public static void main(String[] args) {
 
        drawMap2();
    }

2、可扩展能力强

多态缺点:属性没有多态性,构造方法没有多态性,运行效率低

四、避免在构造方法中调用重写

class B {
 
     public B() {
       func();
       }
 
     public void func() {
       System.out.println("B.func()");
       }
} 

class D extends B { 
         private int num = 1;
         @Override 
         public void func() {
          System.out.println("D.func() " + num);
       }
}

public class test2 { 
 public static void main(String[] args) {
    D d = new D();
 }
}

结果:

说明在构造方法中也能发生动态绑定

构造D对象的同时会调用B的构造方法,B的构造方法中调用了func方法,此时会触发动态绑定,会调用到D中的func(),此时D对象自身还没有构造,此时num处在未初始化的状态。

所以在构造方法中尽量不要调用重写的方法

五、向下转型:

把父类引用给到子类

public static void main2(String[] args) {

         Animal animal = new Dog("小燕",19);
         //Dog dog = animal;
         //报错原因,不是所有的动物都是狗,把大范围的东西给到小范围
        //强转
        Dog dog = (Dog)animal;
        dog.bark();
        
    }

但是存在不安全

public static void main2(String[] args) {
         Animal animal = new Dog("小燕",19);
         
        Bird bird = (Bird)animal;
        //但是animal是狗,虽然代码没标错,但是运行出错,出现转化错误
    }

解决方法加上if判断语句

 public static void main(String[] args) {
        Animal animal = new Dog("小燕",19);
        if(animal instanceof Bird){
            Bird bird = (Bird)animal;
        }else
        {
            System.out.println("animal instanceof Bird not");
        }
    }

  • 31
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
多态是面向对象编程中的一个重要概念,它允许同一类型的对象在不同的情况下表现出不同的行为。它有以下优势和劣势: 优势: 1. 可扩展性:多态允许在不修改现有代码的情况下增加新的子类或实现类,并使用它们作为父类或接口进行操作。这样可以使代码更加灵活和可扩展。 2. 可替换性:多态通过将对象视为其父类或接口类型,使得可以在运行时动态地替换对象,从而实现代码的解耦和重用。 3. 简化代码:多态可以通过将一组具有相似行为的对象抽象为一个父类或接口,从而减少代码的冗余和复杂性。 劣势: 1. 性能损失:由于多态需要在运行时确定实际调用方法,可能会引入一定的性能损失。相比于直接调用具体类型的方法多态需要进行额外的查找和判断操作。 2. 限制访问:多态只能访问父类或接口中定义的方法和属性,不能直接访问子类或实现类特有的方法和属性。如果需要使用特定子类或实现类的功能,就需要进行类型转换。 3. 可读性降低:多态的使用可能会使代码变得更加抽象和难以理解,特别是在复杂的继承关系和多层级的接口实现中。 总结来说,多态在提高代码的灵活性和可扩展性方面具有优势,但也可能带来一些性能损失和可读性降低的问题。在具体应用中,需要权衡利弊,并根据实际需求进行选择和设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值