Java语言里什么叫做多态

Java语言里什么叫做多态?多态编写的程序会不会造成内存的占用?多态和多对象是一个意思么?

【以下回答由 GPT 生成】

回答:

Java语言中的多态是指一个对象变量可以引用不同类型的对象,并根据对象类型的不同而表现出不同的行为。具体来说,多态性允许我们使用父类引用来引用子类对象,并在运行时动态地确定最终使用的方法。这样可以提高代码的灵活性和可扩展性。

在Java中实现多态有两个必要条件:继承和重写。我们需要定义一个父类,然后通过继承创建子类,子类可以使用父类的方法并且可以重写这些方法来实现多态。

多态编写的程序不会造成额外的内存占用。实际上,多态性可以帮助我们节省内存,因为我们可以通过多态性实现用更少的代码来处理不同类型的对象。多态性实现的方式是使用指向子类对象的父类引用,而不需要创建子类对象。

多对象是指可以创建多个对象,每个对象都有自己的属性和方法。多对象与多态性不是同一个概念。多对象是通过创建不同的对象来实现多个实例,每个对象都是独立的,有自己独立的内存空间。而多态性是同一个引用指向不同类型的对象,同一个引用可以根据实际指向的对象类型的不同,表现出不同的行为。

总结起来,多态性是Java语言中的一个重要概念,它允许我们使用父类引用来引用子类对象,并根据对象类型的不同而表现出不同的行为。多态性编写的程序不会造成额外的内存占用,它可以提高代码的灵活性和可扩展性。而多对象是指可以创建多个对象,每个对象都有自己的属性和方法,是与多态性不同的概念。



【相关推荐】



如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

多态是指,子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现,实现多态的方式有三种,继承、接口类以及duck-typing

1 继承方式实现多态

创建一个动态数组,以及一个排序的动态数组子类来看看多态的特性:

package com.example.designpattern;


/**
 * 动态数组
 * @author tianmaolin
 */
public class DynamicArray {
    private static final int DEFAULT_CAPACITY = 10;
    /**
     * The Size.
     */
    protected int size = 0;
    /**
     * The Capacity.
     */
    protected int capacity = DEFAULT_CAPACITY;
    /**
     * The Elements.
     */
    protected Integer[] elements = new Integer[DEFAULT_CAPACITY];

    /**
     * Size int.
     *
     * @return the int
     */
    public int size() { return this.size; }

    /**
     * Get integer.
     *
     * @param index the index
     * @return the integer
     */
    public Integer get(int index) { return elements[index];}
    //...省略n多方法...

    /**
     * Add.
     *
     * @param e the e
     */
    public void add(Integer e) {
        ensureCapacity();
        elements[size++] = e;
    }

    /**
     * Ensure capacity.
     */
    protected void ensureCapacity() {
        //...如果数组满了就扩容...代码省略...
    }
}

/**
 * 排序动态数组
 * @author tianmaolin
 */
class SortedDynamicArray extends DynamicArray {
    @Override
    public void add(Integer e) {
        ensureCapacity();
        int i;
        for (i = size-1; i>=0; --i) { //保证数组中的数据有序
            if (elements[i] > e) {
                elements[i+1] = elements[i];
            } else {
                break;
            }
        }
        elements[i+1] = e;
        ++size;
    }
}

/**
 1. 测试排序
 2. @author tianmaolin
 */
class Test {
    /**
     * Test.
     *
     * @param dynamicArray the dynamic array
     */
    public static void test(DynamicArray dynamicArray) {
        dynamicArray.add(5);
        dynamicArray.add(1);
        dynamicArray.add(3);
        for (int i = 0; i < dynamicArray.size(); ++i) {
            System.out.println(dynamicArray.get(i));
        }
    }

    /**
     * Main.
     *
     * @param args the args
     */
    public static void main(String args[]) {
        DynamicArray dynamicArray = new SortedDynamicArray();
        test(dynamicArray); // 打印结果:1、3、5
    }
}

多态这种特性也需要编程语言提供特殊的语法机制来实现。在上面的例子中,我们用到了三个语法机制来实现多态。

  1. 第一个语法机制是编程语言要支持父类对象可以引用子类对象,也就是可以将 SortedDynamicArray 传递给 DynamicArray。
  2. 第二个语法机制是编程语言要支持继承,也就是 SortedDynamicArray 继承了 DynamicArray,才能将 SortedDyamicArray 传递给 DynamicArray。
  3. 第三个语法机制是编程语言要支持子类可以重写(override)父类中的方法,也就是 SortedDyamicArray 重写了 DynamicArray 中的 add() 方法。

通过这三种语法机制配合在一起,我们就实现了在 test() 方法中,子类 SortedDyamicArray 替换父类 DynamicArray,执行子类 SortedDyamicArray 的 add() 方法,也就是实现了多态特性。当然除了继承的方式(无论是继承的普通类还是抽象类)

2 接口类方式实现多态

还可以使用接口的方式实现多态:

public interface Iterator {
  boolean hasNext();
  String next();
  String remove();
}

public class Array implements Iterator {
  private String[] data;
 
  public boolean hasNext() { ... }
  public String next() { ... }
  public String remove() { ... }
  //...省略其他方法...
}

public class LinkedList implements Iterator {
  private LinkedListNode head;
  
  public boolean hasNext() { ... }
  public String next() { ... }
  public String remove() { ... }
  //...省略其他方法... 
}

public class Demo {
  private static void print(Iterator iterator) {
    while (iterator.hasNext()) {
      System.out.println(iterator.next());
    }
  }
  
  public static void main(String[] args) {
    Iterator arrayIterator = new Array();
    print(arrayIterator);
    
    Iterator linkedListIterator = new LinkedList();
    print(linkedListIterator);
  }
}

在这段代码中,Iterator 是一个接口类,定义了一个可以遍历集合数据的迭代器。Array 和 LinkedList 都实现了接口类 Iterator。我们通过传递不同类型的实现类(Array、LinkedList)到 print(Iterator iterator) 函数中,支持动态的调用不同的 next()、hasNext() 实现。

3 duck-typing实现多态

扩展一下,虽然Java这样的语言目前不支持duck-typing实现多态,多多少少也可以了解一下,一段python代码:

class Logger:
    def record(self):
        print(“I write a log into file.”)
        
class DB:
    def record(self):
        print(“I insert data into db. ”)
        
def test(recorder):
    recorder.record()

def demo():
    logger = Logger()
    db = DB()
    test(logger)
    test(db)

从这段代码中,我们发现,duck-typing 实现多态的方式非常灵活。Logger 和 DB 两个类没有任何关系,既不是继承关系,也不是接口和实现的关系,但是只要它们都有定义了 record() 方法,就可以被传递到 test() 方法中,在实际运行的时候,执行对应的 record() 方法。也就是说,只要两个类具有相同的方法,就可以实现多态,并不要求两个类之间有任何关系,这就是所谓的 duck-typing,是一些动态语言所特有的语法机制。而像 Java 这样的静态语言,通过继承实现多态特性,必须要求两个类之间有继承关系,通过接口实现多态特性,类必须实现对应的接口

解决什么问题

多态特性能提高代码的可扩展性和复用性

  • 多态提高了代码的可扩展性,我们利用多态的特性,仅用一个 print() 函数就可以实现遍历打印不同类型(Array、LinkedList)集合的数据。当再增加一种要遍历打印的类型的时候,比如 HashMap,我们只需让 HashMap 实现 Iterator 接口,重新实现自己的 hasNext()、next() 等方法就可以了,完全不需要改动 print() 函数的代码。所以说,。
  • 多态提高了代码的可复用性,如果我们不使用多态特性,我们就无法将不同的集合类型(Array、LinkedList)传递给相同的函数(print(Iterator iterator) 函数)。我们需要针对每种要遍历打印的集合,分别实现不同的 print() 函数,比如针对 Array,我们要实现 print(Array array) 函数,针对 LinkedList,我们要实现 print(LinkedList linkedList) 函数。而利用多态特性,我们只需要实现一个 print() 函数的打印逻辑,就能应对各种集合数据的打印操作,这显然提高了代码的复用性。

除此之外,多态也是很多设计模式、设计原则、编程技巧的代码实现基础,比如策略模式、基于接口而非实现编程、依赖倒置原则、里式替换原则、利用多态去掉冗长的 if-else 语句等