Java中的内部类详解

news2025/5/10 13:44:28

目录

什么是内部类?

生活中的内部类例子

为什么需要内部类?

生活中的例子

内部类的存在意义

内部类的分类

1. 成员内部类

什么是成员内部类?

成员内部类的特点

如何使用成员内部类?

成员内部类访问外部类同名成员

2. 静态内部类

什么是静态内部类?

静态内部类的特点

静态内部类的使用

静态内部类的方法调用

3. 局部内部类

什么是局部内部类?

局部内部类的特点

局部内部类的使用

4. 匿名内部类

什么是匿名内部类?

匿名内部类的特点

匿名内部类的格式

匿名内部类的使用场景

匿名内部类示例

内部类的实际应用

1. 实现多重继承

2. 封装实现细节

3. 回调机制

内部类与Lambda表达式

内部类编译后的文件命名规则

内部类面试常见问题

1. 内部类的各种差异比较

2. 为什么局部内部类只能访问final局部变量?

内部类与外部类的关系

内部类与外部类的关联

总结


什么是内部类?

内部类就是定义在另一个类内部的类。写在成员位置的,属于外部类的成员。

想象一下我们的日常生活:一台电脑包含CPU、内存、硬盘等组件。从面向对象的角度看,我们可以将电脑看作一个类(Computer),而CPU、内存等组件则可以看作电脑内部的类(CPU, Memory, HardDisk)。这些组件属于电脑,在电脑内部工作,与电脑有紧密的联系。

这就像Java中的内部类概念:一个类定义在另一个类的内部,形成一种"类中有类"的结构。

生活中的内部类例子

// 电脑类
public class Computer {
    private String brand;
    private double price;
    
    // CPU内部类
    class CPU {
        private String model;
        private int cores;
        
        public void run() {
            // CPU可以访问电脑的品牌信息
            System.out.println(brand + "电脑的" + model + "处理器正在运行...");
        }
    }
    
    // 显卡内部类
    class GraphicsCard {
        private String model;
        private int memory;
        
        public void display() {
            // 显卡也可以访问电脑的信息
            System.out.println(brand + "电脑的" + model + "显卡正在渲染画面...");
        }
    }
    
    // 电脑使用内部组件
    public void start() {
        CPU cpu = new CPU();
        cpu.model = "Intel i7";
        cpu.run();
        
        GraphicsCard gc = new GraphicsCard();
        gc.model = "NVIDIA RTX 3080";
        gc.display();
    }
}

在这个例子中:

  • Computer是外部类,代表整台电脑
  • CPUGraphicsCard是内部类,代表电脑的组件
  • 内部类可以访问外部类的属性(brand)
  • 外部类可以直接创建和使用内部类

这种设计反映了现实世界中的"整体-部分"关系,内部类就像是外部类的一个组成部分。

public class Outer {  // 外部类
    private int num = 10;
    
    class Inner {  // 内部类
        // 内部类的代码
    }
}

为什么需要内部类?

理解内部类存在的原因,可以通过更多的生活例子来理解:

生活中的例子

  1. 汽车与发动机

    • 汽车(Car)是外部类,发动机(Engine)是内部类
    • 发动机是汽车的核心组件,与汽车紧密相关
    • 发动机需要访问汽车的各种状态(油量、温度等)
    • 一般不会将发动机单独使用,它主要为汽车服务
  2. 手机与应用程序

    • 手机(Phone)是外部类,应用程序(App)是内部类
    • 应用程序需要访问手机的功能(摄像头、存储空间等)
    • 应用程序主要为手机提供特定功能

内部类的存在意义

  1. 提高封装性

    • 内部类可以访问外部类的所有成员,包括私有成员
    • 内部类本身可以对外隐藏,只有外部类能访问它
    • 实现高内聚、低耦合的设计理念
  2. 实现多重继承

    • Java不支持类的多重继承,但内部类可以继承其他类
    • 通过在一个类中创建多个内部类,每个内部类继承不同的类,实现类似多重继承的效果
  3. 更好地实现回调机制

    • 匿名内部类特别适合用于事件处理和回调机制
    • 简化了接口实现的代码结构
  4. 隐藏实现细节

    • 将实现细节隐藏在外部类内部,对外只暴露必要的接口
    • 如集合框架中的迭代器实现,就是通过内部类完成的
  5. 组织逻辑上紧密相关的类

    • 当一个类只对另一个类有用时,将其定义为内部类可以更好地组织代码
    • 体现了"has-a"关系中的"a"是专属于宿主对象的情况

内部类的分类

Java中的内部类主要分为四种类型:

  1. 成员内部类:写在类成员位置的内部类
  2. 静态内部类:使用static修饰的内部类
  3. 局部内部类:定义在方法中的内部类
  4. 匿名内部类:没有名字的内部类,隐藏了类的名字

1. 成员内部类

什么是成员内部类?

成员内部类是定义在类成员位置的内部类,就像一个普通的成员变量一样。

成员内部类的特点

  • 可以使用外部类的所有成员和方法,即使是private的
  • 在JDK 16之前,成员内部类中不能定义静态成员
  • 成员内部类可以被访问修饰符修饰:privatedefaultprotectedpublic
  • 成员内部类不能脱离外部类对象独立存在,需要先创建外部类对象

如何使用成员内部类?

方式一:在外部类中直接创建内部类对象并使用

public class Outer {
    private int num = 10;
    
    // 成员内部类
    class Inner {
        public void show() {
            System.out.println("外部类成员变量num=" + num);
        }
    }
    
    // 在外部类中使用内部类
    public void method() {
        Inner i = new Inner();
        i.show();
    }
}

方式二:在其他类中使用成员内部类

public class Test {
    public static void main(String[] args) {
        // 先创建外部类对象
        Outer outer = new Outer();
        
        // 再创建内部类对象
        Outer.Inner inner = outer.new Inner();
        
        // 使用内部类方法
        inner.show();
    }
}

成员内部类访问外部类同名成员

如果内部类和外部类有同名的成员变量,可以使用外部类名.this.成员变量来访问外部类的成员:

public class Outer {
    private int num = 10;
    
    class Inner {
        private int num = 20;
        
        public void show() {
            int num = 30;
            System.out.println("局部变量:" + num);  // 30
            System.out.println("内部类成员变量:" + this.num);  // 20
            System.out.println("外部类成员变量:" + Outer.this.num);  // 10
        }
    }
}

2. 静态内部类

什么是静态内部类?

静态内部类是使用static关键字修饰的内部类,是一种特殊的成员内部类。

静态内部类的特点

  • 静态内部类只能访问外部类的静态成员,不能直接访问非静态成员
  • 静态内部类可以包含静态成员,也可以包含非静态成员
  • 创建静态内部类对象时,不需要依赖外部类对象

静态内部类的使用

创建静态内部类对象的格式

外部类名.内部类名 对象名 = new 外部类名.内部类名();

示例代码

public class Car {  // 外部类
    private String carName;
    private static int carAge = 10;
    
    // 静态内部类
    static class Engine {
        private String engineName;
        
        public void show() {
            // 可以访问外部类静态成员
            System.out.println("汽车年龄:" + carAge);
            
            // 不能访问外部类非静态成员
            // System.out.println(carName); // 编译错误
        }
    }
}

// 使用静态内部类
public class Test {
    public static void main(String[] args) {
        // 直接创建静态内部类对象,不需要外部类对象
        Car.Engine engine = new Car.Engine();
        engine.show();
    }
}

静态内部类的方法调用

  1. 调用静态内部类的静态方法外部类名.内部类名.方法名();
  2. 调用静态内部类的非静态方法:先创建静态内部类对象,再用对象调用方法
public class Outer {
    // 静态内部类
    static class Inner {
        // 静态方法
        public static void staticMethod() {
            System.out.println("静态内部类的静态方法");
        }
        
        // 非静态方法
        public void normalMethod() {
            System.out.println("静态内部类的非静态方法");
        }
    }
}

// 调用方法
public class Test {
    public static void main(String[] args) {
        // 调用静态方法
        Outer.Inner.staticMethod();
        
        // 调用非静态方法
        Outer.Inner inner = new Outer.Inner();
        inner.normalMethod();
    }
}

3. 局部内部类

什么是局部内部类?

局部内部类是定义在方法中的类,像局部变量一样,只能在定义它的方法内部使用。

局部内部类的特点

  • 只能在定义它的方法内部使用
  • 可以访问外部类的所有成员
  • 可以访问方法中的final或effectively final(Java 8以后)的局部变量

局部内部类的使用

public class Outer {
    private int outerField = 10;
    
    public void method() {
        final int localVar = 20;  // final局部变量
        int effectivelyFinal = 30;  // effectively final变量(不会被修改)
        
        // 局部内部类
        class LocalInner {
            public void show() {
                // 访问外部类成员
                System.out.println("外部类成员:" + outerField);
                
                // 访问方法中的局部final变量
                System.out.println("局部变量:" + localVar);
                
                // 访问effectively final变量
                System.out.println("Effectively final变量:" + effectivelyFinal);
            }
        }
        
        // 创建局部内部类对象并调用方法
        LocalInner inner = new LocalInner();
        inner.show();
        
        // 注意:这里不能修改effectivelyFinal的值
        // effectivelyFinal = 40; // 这样会导致编译错误
    }
}

4. 匿名内部类

什么是匿名内部类?

匿名内部类是隐藏了名字的内部类,本质上是一个没有名字的局部内部类,它必须继承一个类或实现一个接口。

匿名内部类的特点

  • 没有显式的类名
  • 在声明的同时完成实例化
  • 一般用于实现接口或继承类
  • 编译后会生成 外部类名$数字.class 文件

匿名内部类的格式

new 类名或接口名() {
    // 重写方法
};

匿名内部类的使用场景

当接口的实现类(或父类的子类)只使用一次时,可以使用匿名内部类简化代码。

匿名内部类示例

1. 实现接口的匿名内部类

public class Test {
    public static void main(String[] args) {
        // 使用匿名内部类实现Runnable接口
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("这是匿名内部类实现的run方法");
            }
        };
        
        new Thread(r).start();
        
        // 更简洁的写法
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("直接创建匿名内部类");
            }
        }).start();
    }
}

2. 继承类的匿名内部类

abstract class Animal {
    public abstract void eat();
}

public class Test {
    public static void main(String[] args) {
        // 使用匿名内部类继承抽象类
        Animal a = new Animal() {
            @Override
            public void eat() {
                System.out.println("狗吃骨头");
            }
        };
        
        a.eat();
    }
}

3. 带参数的匿名内部类

interface Calculator {
    int calculate(int a, int b);
}

public class Test {
    public static void main(String[] args) {
        // 使用匿名内部类实现带参数的接口
        Calculator c = new Calculator() {
            @Override
            public int calculate(int a, int b) {
                return a + b;
            }
        };
        
        System.out.println("计算结果:" + c.calculate(10, 20));
    }
}

内部类的实际应用

1. 实现多重继承

Java不支持类的多继承,但可以通过内部类模拟实现:

class A {
    public void methodA() {
        System.out.println("来自A类的方法");
    }
}

class B {
    public void methodB() {
        System.out.println("来自B类的方法");
    }
}

// 通过内部类实现对A和B功能的同时使用
class C {
    // 继承A的内部类
    private class InnerA extends A {
        public void methodA() {
            super.methodA();
        }
    }
    
    // 继承B的内部类
    private class InnerB extends B {
        public void methodB() {
            super.methodB();
        }
    }
    
    // 对外提供方法
    public void methodA() {
        new InnerA().methodA();
    }
    
    public void methodB() {
        new InnerB().methodB();
    }
}

2. 封装实现细节

内部类可以用来隐藏实现细节,如集合类中的迭代器实现:

public class MyArrayList<E> {
    private Object[] elements;
    private int size;
    
    // 其他代码...
    
    // 使用内部类实现迭代器
    private class MyIterator implements Iterator<E> {
        private int cursor;
        
        @Override
        public boolean hasNext() {
            return cursor < size;
        }
        
        @Override
        public E next() {
            if (cursor >= size) {
                throw new NoSuchElementException();
            }
            return (E) elements[cursor++];
        }
    }
    
    // 对外提供获取迭代器的方法
    public Iterator<E> iterator() {
        return new MyIterator();
    }
}

3. 回调机制

匿名内部类常用于实现事件监听和回调:

// 在Swing中使用匿名内部类处理按钮点击
JButton button = new JButton("点击我");
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("按钮被点击了!");
    }
});

内部类与Lambda表达式

在Java 8之后,对于只有一个抽象方法的接口(函数式接口),可以使用Lambda表达式代替匿名内部类,使代码更加简洁:

// 使用匿名内部类
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("使用匿名内部类");
    }
};

// 使用Lambda表达式
Runnable r2 = () -> System.out.println("使用Lambda表达式");

// 启动线程
new Thread(r1).start();
new Thread(r2).start();

// 直接使用Lambda创建线程
new Thread(() -> System.out.println("直接使用Lambda")).start();

内部类编译后的文件命名规则

编译含有内部类的Java文件后,会生成多个.class文件:

  1. 成员内部类外部类名$内部类名.class
  2. 静态内部类外部类名$内部类名.class
  3. 局部内部类外部类名$数字内部类名.class
  4. 匿名内部类外部类名$数字.class

例如,如果有以下类定义:

public class Outer {
    class Inner {}
    static class StaticInner {}
    
    public void method() {
        class LocalInner {}
        
        new Runnable() {
            public void run() {}
        };
    }
}

编译后将生成以下文件:

  • Outer.class
  • Outer$Inner.class
  • Outer$StaticInner.class
  • Outer$1LocalInner.class
  • Outer$1.class(匿名内部类)

内部类面试常见问题

1. 内部类的各种差异比较

特性成员内部类静态内部类局部内部类匿名内部类
定义位置类成员位置类成员位置方法内部方法内部
访问修饰符可以使用可以使用不能使用不能使用
是否可静态JDK16前不可可以不可以不可以
是否需要外部类对象需要不需要需要需要
是否可以访问外部类非静态成员可以不可以可以可以
是否可以访问外部类静态成员可以可以可以可以

2. 为什么局部内部类只能访问final局部变量?

这是因为局部变量在方法结束后就会被销毁,而局部内部类对象可能在方法结束后仍然存在。如果允许内部类修改局部变量,当变量已经被销毁后,内部类却还引用这个变量,会导致数据不一致。为了解决这个问题,Java要求局部内部类访问的局部变量必须是final的(Java 8后可以是effectively final)。

内部类与外部类的关系

内部类与外部类的关联

  1. 内部类持有外部类的引用

    • 非静态内部类隐式持有外部类的引用(Outer.this
    • 这也是为什么非静态内部类能访问外部类所有成员的原因
    • 注意:这可能导致内存泄漏,当内部类对象生命周期比外部类对象长时
  2. 编译后的实现细节

    • 内部类编译后会生成独立的.class文件
    • 非静态内部类的构造函数会隐式接收外部类的引用
    • 访问外部类私有成员时,编译器会生成特殊的访问方法
// 编译前的代码
public class Outer {
    private int x = 10;
    
    class Inner {
        void access() {
            System.out.println(x);  // 访问外部类的私有成员
        }
    }
}

// 编译器处理后的逻辑(简化表示)
public class Outer {
    private int x = 10;
    
    // 为内部类提供的访问方法
    static int access$000(Outer outer) {
        return outer.x;
    }
    
    class Inner {
        final Outer this$0;  // 持有外部类引用
        
        Inner(Outer outer) {
            this$0 = outer;  // 保存外部类引用
        }
        
        void access() {
            System.out.println(Outer.access$000(this$0));  // 通过特殊方法访问
        }
    }
}

总结

内部类是Java中一个强大的特性,它允许我们在一个类中定义另一个类,增强了封装性和代码的组织结构。主要分为四种类型:

  • 成员内部类:像普通成员一样的内部类
  • 静态内部类:使用static修饰的内部类
  • 局部内部类:定义在方法中的内部类
  • 匿名内部类:没有名字的内部类

内部类存在的主要意义

  1. 提高封装性,隐藏实现细节
  2. 实现类似多重继承的功能
  3. 更好地组织逻辑上紧密相关的类
  4. 简化事件处理和回调机制的实现
  5. 提供更灵活的访问控制

使用内部类的建议

  • 当一个类只对另一个类有用时,考虑使用内部类
  • 需要访问外部类私有成员时,使用非静态内部类
  • 不需要访问外部类实例成员时,优先使用静态内部类(减少内存引用)
  • 仅在方法内使用的类,定义为局部内部类
  • 实现接口或扩展类且只使用一次时,考虑使用匿名内部类或Lambda表达式

随着Java的发展,内部类与Lambda表达式、方法引用等新特性结合使用,可以使代码更加简洁和易读。掌握内部类是成为Java高级开发者的必备技能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2372343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Edu教育邮箱申请2025年5月

各位好&#xff0c;这里是aigc创意人竹相左边 如你所见&#xff0c;这里是第3部分 现在是选择大学的学科专业 选专业的时候记得考虑一下当前的时间日期。 比如现在是夏天&#xff0c;所以你选秋天入学是合理的。

STM32-TIM定时中断(6)

目录 一、TIM介绍 1、TIM简介 2、定时器类型 3、基本定时器 4、通用定时器 5、定时中断基本结构 6、时基单元的时序 &#xff08;1&#xff09;预分频器时序 &#xff08;2&#xff09;计数器时序 7、RCC时钟树 二、定时器输出比较功能&#xff08;PWM&#xff09; …

Modbus RTU 详解 + FreeMODBUS移植(附项目源码)

文章目录 前言一、Modbus RTU1.1 通信方式1.2 模式特点1.3 数据模型1.4 常用功能码说明1.5 异常响应码1.6 通信帧格式1.6.1 示例一&#xff1a;读取保持寄存器&#xff08;功能码 0x03&#xff09;1.6.2 示例二&#xff1a;写单个线圈&#xff08;功能码 0x05&#xff09;1.6.3…

对称加密算法(AES、ChaCha20和SM4)Python实现——密码学基础(Python出现No module named “Crypto” 解决方案)

文章目录 一、对称加密算法基础1.1 对称加密算法的基本原理1.2 对称加密的主要工作模式 二、AES加密算法详解2.1 AES基本介绍2.2 AES加密过程2.3 Python中实现AES加密Python出现No module named “Crypto” 解决方案 2.4 AES的安全考量 三、ChaCha20加密算法3.1 ChaCha20基本介…

【软件设计师:存储】16.计算机存储系统

一、主存储器 存储器是计算机系统中的记忆设备,用来存放程序和数据。 计算机中全部信息,包括输入的原始数据、计算机程序、中间运 行结果和最终运行结果都保存在存储器中。 存储器分为: 寄存器Cache(高速缓冲存储器)主存储器辅存储器一、存储器的存取方式 二、存储器的性…

WebRTC通信原理与流程

1、服务器与协议相关 1.1 STUN服务器 图1.1.1 STUN服务器在通信中的位置图 1.1.1 STUN服务简介 STUN&#xff08;Session Traversal Utilities for NAT&#xff0c;NAT会话穿越应用程序&#xff09;是一种网络协议&#xff0c;它允许位于NAT&#xff08;或多重 NAT&#xff09;…

Java版ERP管理系统源码(springboot+VUE+Uniapp)

ERP系统是企业资源计划&#xff08;Enterprise Resource Planning&#xff09;系统的缩写&#xff0c;它是一种集成的软件解决方案&#xff0c;用于协调和管理企业内各种关键业务流程和功能&#xff0c;如财务、供应链、生产、人力资源等。它的目标是帮助企业实现资源的高效利用…

Redis总结(六)redis持久化

本文将简单介绍redis持久化的两种方式 redis提供了两种不同级别的持久化方式&#xff1a; RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保…

PMIC电源管理模块的PCB设计

目录 PMU模块简介 PMU的PCB设计 PMU模块简介 PMIC&#xff08;电源管理集成电路&#xff09;是现代电子设备的核心模块&#xff0c;负责高效协调多路电源的转换、分配与监控。它通过集成DC-DC降压/升压、LDO线性稳压、电池充电管理、功耗状态切换等功能&#xff0c;替代传统分…

华为云Flexus+DeepSeek征文|DeepSeek-V3商用服务开通教程

目录 DeepSeek-V3/R1商用服务开通使用感受 DeepSeek-V3/R1商用服务开通 1、首先需要访问ModelArts Studio_MaaS_大模型即服务_华为云 2、在网站右上角登陆自己的华为云账号&#xff0c;如果没有华为云账号的话&#xff0c;则需要自己先注册一个。 3、接着点击ModelArts Stu…

Qt—鼠标移动事件的趣味小程序:会移动的按钮

1.项目目标 本次根据Qt的鼠标移动事件实现一个趣味小程序&#xff1a;当鼠标移动到按钮时&#xff0c;按钮就会随机出现在置&#xff0c;以至于根本点击不到按钮。​​​​​ 2.项目步骤 首先现在ui界面设计控件(也可以用代码的方式创建&#xff0c;就不多说了) 第一个按钮不需…

鞋样设计软件

Sxy 64鞋样设计软件是一款专业级鞋类设计工具 专为鞋业设计师与制鞋企业开发 该软件提供全面的鞋样设计功能 包括二维开版 三维建模 放码排料等核心模块 支持从草图构思到成品输出的完整设计流程 内置丰富的鞋型数据库与部件库 可快速生成各种鞋款模板 软件采用智能放码技术 精…

LeRobot 项目部署运行逻辑(六)——visualize_dataset_html.py/visualize_dataset.py

可视化脚本包括了两个方法&#xff1a;远程下载 huggingface 上的数据集和使用本地数据集 脚本主要使用两个&#xff1a; 目前来说&#xff0c;ACT 采集训练用的是统一时间长度的数据集&#xff0c;此外&#xff0c;这两个脚本最大的问题在于不能裁剪&#xff0c;这也是比较好…

Windows Server 2025开启GPU分区(GPU-P)部署DoraCloud云桌面

本文描述在ShareStation工作站虚拟化方案的部署过程。 将服务器上部署 Windows Server、DoraCloud&#xff0c;并创建带有vGPU的虚拟桌面。 GPU分区技术介绍 GPU-P&#xff08;GPU Partitioning&#xff09; 是微软在 Windows 虚拟化平台&#xff08;如 Hyper-V&#xff09;中…

TCP套接字通信核心要点

TCP套接字通信核心要点 通信模型架构 客户端-服务端模型 CS架构&#xff1a;客户端发起请求&#xff0c;服务端响应和处理请求双向通道&#xff1a;建立连接后实现全双工通信 服务端搭建流程 核心步骤 创建套接字 int server socket(AF_INET, SOCK_STREAM, 0); 参数说明&am…

【C】初阶数据结构15 -- 计数排序与稳定性分析

本文主要讲解七大排序算法之外的另一种排序算法 -- 计数排序 目录 1 计数排序 1&#xff09; 算法思想 2&#xff09; 代码 3&#xff09; 时间复杂度与空间复杂度分析 &#xff08;1&#xff09; 时间复杂度 &#xff08;2&#xff09; 空间复杂度 4&#xff09; 计…

高性能Python Web 框架--FastAPI 学习「基础 → 进阶 → 生产级」

以下是针对 FastAPI 的保姆级教程&#xff0c;包含核心概念、完整案例和关键注意事项&#xff0c;采用「基础 → 进阶 → 生产级」的三阶段教学法&#xff1a; 一、FastAPI介绍 FastAPI 是一个现代化的、高性能的 Python Web 框架&#xff0c;专门用于构建 APIs&#xff08;应…

Qt QML自定义LIstView

QML ListView组合拳做列表&#xff0c;代码不可直接复制使用&#xff0c;需要小改 先上图看效果 样式1 样式2 样式3 原理&#xff1a;操作&#xff1a;技术点:代码片段&#xff1a; 先上图看效果 样式1 三个表格组合成要给&#xff0c;上下滚动时&#xff0c;三个同时滚动&am…

C++进阶--红黑树的实现

文章目录 红黑树的实现红黑树的概念红黑树的规则红黑树的效率 红黑树的实现红黑树的结构红黑树的插入变色单旋&#xff08;变色&#xff09;双旋&#xff08;变色&#xff09; 红黑树的查找红黑树的验证 总结&#xff1a;结语 很高兴和大家见面&#xff0c;给生活加点impetus&a…

WPF之值转换器

文章目录 目录什么是值转换器IValueConverter接口Convert方法ConvertBack方法 创建和使用值转换器定义转换器类在XAML中使用转换器转换器参数&#xff08;ConverterParameter&#xff09; 常用转换器实现布尔值转可见性&#xff08;BoolToVisibilityConverter&#xff09;数值转…