【Java基础小记】0824

Java多态

引言

介绍多态的概念

多态是面向对象编程(OOP)中的一个核心概念。在编程中,多态指的是一种能力,使得一个对象可以以多种不同的形式出现,或使得同一个方法调用在不同的上下文中表现出不同的行为。

多态主要体现在以下几个方面:

  • 方法重载(Overloading):在同一个类中定义多个方法名相同但参数列表不同的方法。方法重载允许在不同的场景下使用不同的参数调用相同的方法名称。

  • 方法重写(Overriding):子类可以提供对父类方法的具体实现。通过重写,子类能够改变或扩展父类方法的行为,实现不同的功能,而不需要改变父类的代码。

  • 接口和抽象类:通过接口和抽象类,可以实现运行时多态,使得不同的类可以以相同的接口进行操作,从而使代码更加灵活和可扩展。

多态在面向对象编程中的重要性

多态在面向对象编程中的重要性主要体现在以下几个方面:

  • 代码的灵活性和可扩展性:

多态允许程序在运行时动态地选择对象的行为,使得程序可以更加灵活地适应变化。通过定义接口或抽象类,系统可以根据需要扩展新功能,而不需要修改现有代码。

  • 代码的重用性:

通过方法重载和重写,可以复用代码,减少重复代码的编写。例如,多个类可以实现相同的方法名,但在各自的上下文中有不同的实现,这样就避免了代码的重复编写。

  • 接口和抽象类的设计:

通过多态,程序设计者可以定义通用接口或抽象类,来规范不同实现类的行为。这使得系统可以在不关心具体实现的情况下,处理各种不同的对象,促进了代码的模块化和解耦。

  • 提高代码的可维护性:

多态使得代码更加模块化。由于不同的对象可以通过统一的接口进行操作,因此代码的修改和扩展只需要在相关的子类中进行,而不需要修改所有使用该对象的代码,这减少了系统维护的复杂性。

一、方法重载

方法重载(Overloading)是指在同一个类中定义多个方法名相同但参数列表不同的方法。参数列表的不同可以表现为参数的数量、类型或顺序的不同。方法重载帮助提高代码的可读性和复用性,使得一个方法名可以用于多种不同的操作。

特点:
方法名相同:所有重载的方法具有相同的名字。
参数列表不同:方法的参数数量、类型或顺序至少有一个不同。
返回类型可以不同:虽然方法的返回类型可以不同,但它不会影响重载的判定。
在同一个类中定义:方法重载发生在同一个类中。
示例代码
以下是一个Java示例,演示了方法重载的概念:

public class OverloadDemo {

    // 方法重载:不同参数数量
    public void printDetails(String name) {
        System.out.println("Name: " + name);
    }

    public void printDetails(String name, int age) {
        System.out.println("Name: " + name + ", Age: " + age);
    }

    // 方法重载:不同参数类型
    public void printDetails(int id, String name) {
        System.out.println("ID: " + id + ", Name: " + name);
    }

    // 方法重载:不同参数顺序
    public void printDetails(String name, double salary) {
        System.out.println("Name: " + name + ", Salary: " + salary);
    }

    public static void main(String[] args) {
        OverloadDemo demo = new OverloadDemo();

        demo.printDetails("Alice");                // 调用第一个重载方法
        demo.printDetails("Bob", 30);              // 调用第二个重载方法
        demo.printDetails(101, "Charlie");        // 调用第三个重载方法
        demo.printDetails("Diana", 50000.0);      // 调用第四个重载方法
    }
}

说明:
printDetails(String name):此方法接收一个String类型的参数。
printDetails(String name, int age):此方法接收一个String和一个int类型的参数。
printDetails(int id, String name):此方法接收一个int类型和一个String类型的参数,参数顺序与其他方法不同。
printDetails(String name, double salary):此方法接收一个String和一个double类型的参数,参数类型与其他方法不同。

二、方法重写

方法重写(Overriding)是指子类提供对父类中已有方法的具体实现。它允许子类根据自身的需求重新定义父类的方法行为。重写的方法在子类中与父类的方法名、参数列表和返回类型都必须完全相同。子类中重写的方法访问权限不能低于父类的方法。

  • 特点:
    方法名相同:子类方法与父类方法的名称必须相同。
    参数列表相同:子类方法的参数类型和数量必须与父类方法一致。
    返回类型相同:子类方法的返回类型必须与父类方法相同。
    访问权限:子类方法的访问权限不能比父类方法更严格。例如,如果父类方法是public,那么子类方法不能是protected或private。
    不能重写static方法:static方法不能被重写,因为它们是属于类而不是对象。

示例代码:

// 父类
class Animal {
    // 父类中的方法
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

// 子类
class Dog extends Animal {
    // 重写父类中的方法
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

// 测试重写
public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        myAnimal.makeSound(); // 输出: Animal makes a sound

        Dog myDog = new Dog();
        myDog.makeSound(); // 输出: Dog barks

        // 父类引用指向子类对象
        Animal anotherAnimal = new Dog();
        anotherAnimal.makeSound(); // 输出: Dog barks
    }
}

说明:
Animal类定义了一个makeSound方法。
Dog类继承自Animal并重写了makeSound方法,提供了自己特定的实现。
在main方法中,通过父类引用Animal指向子类对象Dog时,调用的是子类Dog中重写的方法。这展示了方法重写的多态性特征。

五个示例

示例 1: 基本的多态性

// 父类
class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

// 子类
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat meows");
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Dog();
        myAnimal.makeSound(); // 输出: Dog barks
        
        myAnimal = new Cat();
        myAnimal.makeSound(); // 输出: Cat meows
    }
}

示例 2: 方法重载和多态

class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }

    public String add(String a, String b) {
        return a + b;
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        
        System.out.println(calc.add(5, 10));       // 输出: 15
        System.out.println(calc.add(5.5, 10.5));   // 输出: 16.0
        System.out.println(calc.add("Hello, ", "World!")); // 输出: Hello, World!
    }
}

示例 3: 多态与接口

// 接口
interface Drawable {
    void draw();
}

// 实现接口的类
class Circle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing a Circle");
    }
}

class Rectangle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing a Rectangle");
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        Drawable d;
        
        d = new Circle();
        d.draw(); // 输出: Drawing a Circle
        
        d = new Rectangle();
        d.draw(); // 输出: Drawing a Rectangle
    }
}

示例 4: 多态与抽象类

// 抽象类
abstract class Shape {
    abstract void draw();
}

// 具体类
class Triangle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a Triangle");
    }
}

class Square extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a Square");
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        Shape s;
        
        s = new Triangle();
        s.draw(); // 输出: Drawing a Triangle
        
        s = new Square();
        s.draw(); // 输出: Drawing a Square
    }
}

示例 5: 多态与集合

import java.util.ArrayList;
import java.util.List;

// 父类
class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

// 子类
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat meows");
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<>();
        animals.add(new Dog());
        animals.add(new Cat());
        
        for (Animal animal : animals) {
            animal.makeSound();
        }
        // 输出:
        // Dog barks
        // Cat meows
    }
}

Last

多态的优势
代码复用:通过方法重载和重写提高代码的复用性。
灵活性和可扩展性:增强代码的灵活性,支持新的功能和实现。
维护性:使代码更加模块化,便于维护和扩展。

二叉树

二叉树是计算机科学中的一种重要数据结构,它具有广泛的应用,如在表达式求值、排序、查找等方面。以下是关于二叉树的一些基本知识和概念:

1. 二叉树的定义

二叉树是每个节点最多有两个子节点的树形结构。每个节点通常包含三个部分:

数据(值)
左子节点(指向左子树的引用)
右子节点(指向右子树的引用)

2. 二叉树的类型

完全二叉树:

除了最底层外,其他每一层的节点都达到最大。
最底层的节点都尽量集中在左侧。
满二叉树:

每个节点都有两个子节点(除了叶子节点)。
平衡二叉树(或 AVL 树):

每个节点的左子树和右子树的高度差不超过1。
二叉搜索树(BST):

对于每个节点,左子树的所有节点都小于该节点,右子树的所有节点都大于该节点。
堆(Heap):

最大堆:每个节点的值都大于或等于其子节点的值。
最小堆:每个节点的值都小于或等于其子节点的值。

3. 二叉树的基本操作

遍历:

前序遍历(Pre-order Traversal):访问顺序为根节点 -> 左子树 -> 右子树。
中序遍历(In-order Traversal):访问顺序为左子树 -> 根节点 -> 右子树。
后序遍历(Post-order Traversal):访问顺序为左子树 -> 右子树 -> 根节点。
层序遍历(Level-order Traversal):逐层访问,每层从左到右。
插入:

根据二叉树的类型(如二叉搜索树),将新节点插入到适当的位置。
删除:

删除节点时,可能需要调整树结构以保持二叉树的性质。
查找:

在二叉搜索树中,查找操作可以在 O(log n) 的时间复杂度内完成(假设树是平衡的)。

4. 二叉树的应用

表达式树:

用于表示数学表达式,通常用于计算机代数系统中。
决策树:

用于机器学习中的分类和回归任务。
文件系统:

许多文件系统使用树结构来管理目录和文件。
数据库索引:

B 树和 B+ 树是数据库系统中常用的索引结构,具有良好的性能特性。

5. 实现示例(Java)

// 二叉树节点定义
class TreeNode {
    int value;
    TreeNode left;
    TreeNode right;
    
    TreeNode(int value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }
}

// 二叉树遍历
public class BinaryTree {
    // 前序遍历
    public void preOrder(TreeNode root) {
        if (root == null) return;
        System.out.print(root.value + " ");
        preOrder(root.left);
        preOrder(root.right);
    }
    
    // 中序遍历
    public void inOrder(TreeNode root) {
        if (root == null) return;
        inOrder(root.left);
        System.out.print(root.value + " ");
        inOrder(root.right);
    }
    
    // 后序遍历
    public void postOrder(TreeNode root) {
        if (root == null) return;
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.value + " ");
    }

    // 层序遍历
    public void levelOrder(TreeNode root) {
        if (root == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            System.out.print(node.value + " ");
            if (node.left != null) queue.offer(node.left);
            if (node.right != null) queue.offer(node.right);
        }
    }
    
    public static void main(String[] args) {
        // 构建一个简单的二叉树
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
        
        BinaryTree tree = new BinaryTree();
        
        System.out.println("前序遍历:");
        tree.preOrder(root);
        
        System.out.println("\n中序遍历:");
        tree.inOrder(root);
        
        System.out.println("\n后序遍历:");
        tree.postOrder(root);
        
        System.out.println("\n层序遍历:");
        tree.levelOrder(root);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值