里氏替换原则:Java 面向对象设计的基石法则
一、原则起源与核心定义
20 世纪 80 年代,计算机科学家芭芭拉・里氏(Barbara Liskov)在一篇论文中首次提出了里氏替换原则(Liskov Substitution Principle,LSP),这成为面向对象设计的重要理论基础。该原则的核心定义是:所有引用父类对象的地方,必须能透明地使用其子类对象而不产生任何异常或逻辑错误。换句话说,子类必须能够完全替代父类,且程序的正确性不会受到影响。
在 Java 语言中,这一原则体现为子类对父类的方法重写必须满足特定的契约关系。里氏本人给出了形式化的定义:如果对每一个类型为 S 的对象 o1,都存在类型为 T 的对象 o2,使得在所有针对 T 编写的程序 P 中,用 o1 替换 o2 后,程序 P 的行为功能不变,那么 S 是 T 的子类型。这为 Java 的继承体系建立了严格的行为规范。
二、原则的核心规范与技术要求
(一)方法契约的保持
-
前置条件不加强:子类方法的前置条件(调用方法时的参数约束)不能比父类更严格。例如父类方法定义为
public void setValue(int value)
,子类不能重写为public void setValue(int value) throws IllegalArgumentException
并在参数小于 0 时抛出异常,因为父类允许任何整数输入。 -
后置条件不减弱:子类方法的后置条件(方法执行后的状态)必须等于或优于父类。假设父类方法承诺返回非空集合,子类重写时不能返回空集合。
-
不变式保持:子类必须保持父类定义的所有不变式属性。例如父类保证 “账户余额不能为负”,子类的任何操作都不能破坏这一不变式。
(二)行为兼容性要求
-
异常兼容性:子类重写方法时不能抛出父类方法未声明的受检异常(Checked Exception),但可以抛出更少或更具体的异常。对于非受检异常(运行时异常),子类方法应保持与父类相同的异常抛出策略。
-
方法语义一致性:子类重写方法的语义必须是父类方法的延续或扩展,而非改变。例如父类
Collection
接口的add
方法承诺添加元素并返回布尔值表示是否成功,子类ArrayList
的实现必须遵守这一语义,不能返回固定值。
(三)状态转换的一致性
子类对象的状态转换必须符合父类定义的状态机模型。例如父类定义的电梯类有 “运行”“停止”“故障” 状态,子类的观光电梯不能在 “停止” 状态下直接进入 “故障” 状态而不经过父类定义的中间状态转换逻辑。
三、违反原则的典型场景与危害
(一)错误继承导致的契约破坏
java
// 父类:几何图形
class Shape {public double getArea() { return 0; }
}// 违反LSP的子类:正方形(假设父类本应是抽象类)
class Square extends Shape {private double side;public Square(double side) { this.side = side; }public double getArea() { return side * side; }
}// 违反LSP的子类:圆形(错误继承)
class Circle extends Shape {private double radius;// 正确实现应覆盖getArea,但假设此处未正确实现public double getArea() { return radius; } // 错误计算逻辑
}
当程序中使用Shape
引用调用getArea()
时,Circle
实例会返回错误结果,破坏程序正确性。
(二)前置条件加强引发的调用异常
java
// 父类方法
class Animal {public void eat(Food food) { /* 处理所有食物 */ }
}// 子类方法加强前置条件
class Cat extends Animal {@Overridepublic void eat(Food food) {if (!(food instanceof Fish)) {throw new IllegalArgumentException("猫只能吃鱼");}super.eat(food);}
}// 客户端代码
Animal animal = new Cat();
animal.eat(new Meat()); // 运行时抛出异常,违反LSP
客户端按照父类契约传递Meat
类型食物时,子类抛出异常,导致程序崩溃。
(三)后置条件减弱带来的逻辑错误
java
// 父类队列
class Queue<T> {public T poll() { return null; } // 承诺返回队列头部元素,可能为null
}// 子类优先队列(错误实现)
class PriorityQueue<T> extends Queue<T> {private List<T> data = new ArrayList<>();@Overridepublic T poll() {if (data.isEmpty()) return null; // 符合父类后置条件T result = data.get(0);data.remove(0);return result; // 实际返回非null对象时,后置条件未减弱}// 假设存在另一个子类错误实现class BadQueue<T> extends Queue<T> {@Overridepublic T poll() { return null; } // 无论是否有元素都返回null,减弱后置条件}
}
当客户端期望队列返回实际元素时,BadQueue
始终返回 null,导致后续逻辑错误。
(四)对程序的具体危害
- 模块间契约失效:破坏类之间的协作契约,导致调用端与实现端的约定不一致。
- 单元测试失效:基于父类的测试用例无法覆盖子类的错误实现,增加调试成本。
- 系统扩展性下降:违反原则的继承体系会形成 “脆弱的继承链”,后续扩展容易引发连锁反应。
- 代码可维护性降低:子类的非预期行为会让维护者难以理解代码逻辑,增加修改风险。
四、正确应用原则的实践策略
(一)基于接口编程而非实现
java
// 定义接口规范
interface Shape {double getArea();
}// 正确实现子类
class Square implements Shape {private double side;public Square(double side) { this.side = side; }public double getArea() { return side * side; }
}class Circle implements Shape {private double radius;public Circle(double radius) { this.radius = radius; }public double getArea() { return Math.PI * radius * radius; }
}
通过接口定义契约,子类实现具体行为,避免错误继承带来的问题。
(二)使用组合替代继承
当子类需要扩展父类功能但无法满足 LSP 时,应采用组合而非继承。例如:
java
// 父类(不适合继承)
class FileReader {public void read() { /* 读取文件 */ }
}// 正确做法:组合而非继承
class EncryptedFileReader {private FileReader fileReader = new FileReader();public void readEncrypted() {// 先解密再调用父类方法fileReader.read();}
}
通过组合方式复用父类功能,避免违反继承契约。
(三)严格的方法重写检查
- 使用
@Override
注解:强制编译器检查方法重写的正确性,避免拼写错误导致的意外重载。 - 契约式设计工具:使用如 JUnit 的契约测试框架,验证子类是否满足父类的前置 / 后置条件。
- 形式化验证:对关键类使用形式化方法(如 Java 的 OpenJDK 中的 JML 工具)进行契约验证。
(四)设计抽象父类的最佳实践
- 定义明确的抽象方法:抽象类应明确声明子类必须实现的方法,避免子类随意重写。
- 封装不变行为:将父类中不变的行为封装为 final 方法,防止子类篡改。
- 文档化契约:在 Javadoc 中明确说明方法的前置条件、后置条件和不变式,指导子类实现。
五、与其他设计原则的协同作用
(一)与开闭原则(OCP)的关系
里氏替换原则是开闭原则的重要支撑。只有子类能够正确替换父类,程序在扩展新功能(添加子类)时才能不修改原有代码,实现对扩展开放、对修改关闭。例如在策略模式中,不同策略子类必须符合策略接口的契约,才能在运行时透明替换。
(二)与依赖倒置原则(DIP)的配合
依赖倒置原则要求高层模块依赖抽象接口,里氏替换原则保证这些抽象接口的具体实现(子类)可以正确替换,两者共同构成稳定的依赖关系。例如 Spring 框架中,Bean 依赖接口而非具体实现类,利用 LSP 实现不同实现类的透明替换。
(三)与单一职责原则(SRP)的关联
每个类应专注于单一职责,子类在继承父类时也应保持职责的一致性。如果子类添加了父类不具备的职责,可能导致违反 LSP,因此保持单一职责有助于维护继承体系的正确性。
六、Java 语言特性对原则的支持
(一)泛型与通配符的应用
java
List<Integer> intList = new ArrayList<>();
List<Number> numberList = intList; // 违反泛型协变规则,Java不允许此操作
// 正确做法:使用通配符
List<? extends Number> numberList = intList; // 符合LSP的协变规则
Java 泛型的协变(Covariance)和逆变(Contravariance)通过通配符实现类型安全的替换,符合里氏替换原则。
(二)final 关键字的使用
将不允许子类重写的方法声明为 final,确保关键行为不被篡改,例如 String 类的方法大多为 final,保证其不可变性。
(三)枚举类型的安全替换
枚举类型隐式继承自 java.lang.Enum,所有枚举实例都是该枚举类型的子类实例,且完全符合父类的行为契约,是 LSP 的完美应用场景。
七、工业级实践中的典型案例
(一)Java 集合框架的设计
Java 集合框架中的List
接口及其实现类(如 ArrayList、LinkedList)严格遵守里氏替换原则。客户端代码可以使用List
引用操作任何具体列表实现,而无需关心具体子类,保证了框架的灵活性和扩展性。
(二)Swing 组件的继承体系
Swing 组件如 JButton、JTextField 等都继承自 JComponent,它们重写父类方法时保持了行为兼容性,使得开发者可以统一处理所有组件事件,而无需为每个子类编写特殊处理逻辑。
(三)Spring 框架的依赖注入
Spring 容器通过依赖接口而非具体类,利用里氏替换原则实现不同实现类的透明切换。例如配置文件中可以替换不同的 DAO 实现类,而无需修改业务层代码。
八、总结与最佳实践清单
里氏替换原则是面向对象设计的 “契约之绳”,它确保继承体系不仅是类型的层次结构,更是行为的契约体系。在 Java 开发中,遵守该原则需要:
- 优先使用组合而非继承:避免为 “代码复用” 而滥用继承,优先考虑组合和委托模式。
- 严格定义抽象契约:通过接口和抽象类明确方法的前置 / 后置条件,并使用文档和工具进行契约验证。
- 进行行为兼容性测试:在子类测试中,除了测试自身功能,还需验证是否满足父类的所有契约。
- 警惕协变与逆变中的陷阱:正确使用 Java 泛型的通配符,避免类型安全问题。
- 持续重构继承体系:当发现子类无法满足 LSP 时,及时通过提取接口、重构父类等方式修复。
遵循里氏替换原则的系统,其继承体系将呈现出稳定、可扩展的特性,为复杂软件系统的长期演进打好坚实基础。在 Java 开发中,这一原则的正确应用不仅能提升代码质量,更能培养开发者严谨的面向对象设计思维,使系统在面对需求变化时保持灵活与健壮。
相关文章:
里氏替换原则:Java 面向对象设计的基石法则
一、原则起源与核心定义 20 世纪 80 年代,计算机科学家芭芭拉・里氏(Barbara Liskov)在一篇论文中首次提出了里氏替换原则(Liskov Substitution Principle,LSP),这成为面向对象设计的重要理论基…...
GBK与UTF-8编码问题(2)
1. 问题现象 在python代码中,用open函数打开文本文件并显示文本内容,中文显示乱码,代码如下。 from tkinter import * import tkinter.filedialogroot Tk() # 给窗口的可视化起名字 root.title(Open File Test)# 设定窗口的大小(长 * 宽) r…...
项目三 - 任务6:回文日期判断
本任务通过判断回文日期,深入学习了Java中日期和字符串处理的相关知识。通过输入年、月、日,生成8位日期字符串,利用StringBuffer的reverse()方法反转字符串,比较原字符串与反转后的字符串是否一致,从而判断是否为回文…...
从零开始掌握FreeRTOS(1)移植到STM32
目录 提前准备 源码文件移植 修改 stm32f10x_it.c 修改 FreeRTOS.h 本章思维导图。 提前准备 学习 FreeRTOS 的第一步就是有一份最工程能够跑在 STM32 上。本篇将记录本人从0搭建一个最基础的移植工程Demo。 要完成这份 Demo,首先我们需要预先准备以下东西&…...
esp32硬件支持AT指令
步骤1:下载AT固件 从乐鑫官网或Git鑫GitHub仓库(https://github.com/espressif/esp-at)获取对应ESP32型号的AT固件(如ESP32-AT.bin)。 步骤2:安装烧录工具 使用 esptool.py(命令行工具&#…...
【神经网络与深度学习】局部最小值和全局最小值
引言 在机器学习和优化问题中,目标函数的优化通常是核心任务。优化过程可能会产生局部最小值或全局最小值,而如何区分它们并选择合适的优化策略,将直接影响模型的性能和稳定性。 在深度学习等复杂优化问题中,寻找全局最小值往往…...
部署安装git-2.49.0.tar.xz
实验环境 git主机:8.10 所需软件 git-2.49.0.tar.xz 实验开始 实验目的:安装升级git2.49.0 编译安装 yum remove git -y --卸载旧版git cd /usr/local/src/ wget https://www.kernel.org/pub/software/scm/git/git-2.49.0.tar.xz …...
SpringBoot的单体和分布式的任务架构
在Spring Boot生态中,定时任务框架的选择需根据架构类型(单体或分布式)和功能需求进行权衡。以下从框架特性、适用场景及Spring Boot集成方式等角度,详细梳理主流的定时任务框架及其分类: 一、单体架构下的定时任务框架…...
第四章 部件篇之按钮矩阵部件
第四章 部件篇之按钮矩阵部件 在 LVGL中, 按钮矩阵部件相当于一系列伪按钮的集合,它按一定的序列来排布这些按钮。值得注意的是,这些伪按钮并不是真正的按钮部件(lv_btn) , 它们只是具有按钮外观的图形&…...
二分查找算法的思路
二分查找思路总结 明确目标与单调性特点: 核心目标:寻找满足某种条件的答案(如最小/最大值)。单调性要求:需要证明你的判断函数具有单调性——即如果某个答案 T 可行,那么大于 T 的答案通常也是可行的&…...
Shell脚本与Xshell的使用、知识点、区别及原理
Shell脚本与Xshell的使用、知识点、区别及原理 Shell脚本 基本概念 Shell脚本是一种为Shell编写的脚本程序,通常用于自动化执行一系列命令。它是在Unix/Linux系统下的命令行解释器与用户交互的接口。 主要知识点 脚本结构:以#!/bin/bash开头…...
【PmHub后端篇】PmHub中基于Redis加Lua脚本的计数器算法限流实现
1 限流的重要性 在高并发系统中,保护系统稳定运行的关键技术有缓存、降级和限流。 缓存通过在内存中存储常用数据,减少对数据库的访问,提升系统响应速度,如浏览器缓存、CDN缓存等多种应用层面。降级则是在系统压力过大或部分服务…...
【递归、搜索与回溯】专题一:递归(二)
📝前言说明: 本专栏主要记录本人递归,搜索与回溯算法的学习以及LeetCode刷题记录,按专题划分每题主要记录:(1)本人解法 本人屎山代码;(2)优质解法 优质代码…...
【Linux】操作系统入门:冯诺依曼体系结构
引言:从一次QQ聊天说起 你是否好奇,当你在键盘上敲下一行文字发送给好友时,计算机内部发生了什么?为什么鼠标点击后程序就能瞬间响应?这一切的答案,都藏在计算机的“心脏”——冯诺依曼体系结构中。 一、硬…...
量化感知训练与 PyTorch 的哪些事
大家好呀!今天咱们要来聊聊一个超厉害的技术——量化感知训练(Quantization-Aware Training,简称 QAT) 在神经网络的世界里,我们总是想方设法地让模型变得更准确、更高效,毕竟谁不想自己的模型在边缘设备上…...
【Mac 从 0 到 1 保姆级配置教程 15】- Python 环境一键安装与配置,就是这么的丝滑
文章目录 前言安装 Python 环境VSCode 配置Python 环境NeoVim 配置 Python 环境(选看)1. Python LSP 配置2. 打开 python 语言支持 最后参考资料系列教程 Mac 从 0 到 1 保姆级配置教程目录,点击即可跳转对应文章: 【Mac 从 0 到 …...
前端学习(3)—— CSS实现热搜榜
效果展示 具体的展示效果如下,可以直接在浏览器显示: 页面分为两部分,一部分是 body 标签里的 html 结构,一部分是 style 标签里的CSS代码(页面布局的部分数据直接在代码里显示了) 一,html结…...
大数据——解决Matplotlib 字体不足问题(Linux\mac\windows)
1、将下载好的字体文件放到文件夹中 谷歌官方字体 import matplotlib print(matplotlib.matplotlib_fname())cp NotoSansSC-Regular.ttf /data/home/miniconda3/envs/python3128/lib/python3.12/site-packages/matplotlib/mpl-data/fonts/ttf/cp wqy-zenhei.ttc /data/home/m…...
嵌入式培训之数据结构学习(二)顺序表与单向链表
目录 一、顺序表 (一)顺序表的基本操作 1、创建顺序表 2、销毁顺序表 3、遍历顺序表 4、尾插,在顺序表的最后插入元素 5、判断表是否满 6、判断表是否空 7、按指定位置插入元素 8、查找元素,根据名字 9、根据名字修改指…...
PyInstaller 打包后 Excel 转 CSV 报错解决方案:“excel file format cannot be determined“
一、问题背景 在使用 Python 开发 Excel 转 CSV 工具时,直接运行脚本(python script.py)可以正常工作,但通过 PyInstaller 打包成可执行文件后,出现以下报错: excel file format cannot be determined, you must specify an engine manually 该问题通常发生在使用pandas…...
鸿蒙 PC 发布之后,想在技术上聊聊它的未来可能
最近鸿蒙 PC 刚发布完,但是发布会没公布太多技术细节,基本上一些细节都是通过自媒体渠道获取,首先可以确定的是,鸿蒙 PC 本身肯定是无法「直接」运行 win 原本的应用,但是可以支持手机上「原生鸿蒙」的应用,…...
HarmonyOS 【诗韵悠然】AI古诗词赏析APP开发实战从零到一系列(一、开篇,项目介绍)
诗词,作为中国传统文化的瑰宝,承载着中华民族几千年的思想智慧和审美情趣。然而,在现代社会快节奏的生活压力下,诗词文化却逐渐被忽视,更多的人感到诗词艰涩深奥,难以亲近。与此同时,虽然市场上…...
实物工厂零件画图案例(上)
文章目录 滑台气缸安装板旋转气缸安装板张紧调节块长度调节块双轴气缸安装板步进电机安装板梯形丝杆轴承座 简介:案例点击此处下载,这次的这几个案例并没有很大的难度,练习这几个案例最为重要的一点就是知道:当你拿到一个实物的时…...
js中的同步方法及异步方法
目录 1.代码说明 2.async修饰的方法和非async修饰的方法的区别 3.不使用await的场景 4.总结 1.代码说明 const saveTem () > {// 校验处理const res check()if (!res) {return}addTemplateRef.value.openModal() } 这段代码中,check方法返回的是true和fal…...
C 语言_基础语法全解析_深度细化版
一、C 语言基本结构 1.1 程序组成部分 一个完整的 C 程序由以下部分组成: 预处理指令:以#开头,在编译前处理 #include <stdio.h> // 引入标准库 #define PI 3.14159 // 定义常量全局变量声明:在所有函数外部定义的变量 int globalVar = 10; // 全局变量函数定义…...
【Linux系列】dd 命令的深度解析与应用实践
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
ETL背景介绍_1:数据孤岛仓库的介绍
1 ETL介绍 1.1 数据孤岛 随着企业内客户数据大量的涌现,单个数据库已不再足够。为了储存这些数据,公司通常会建立多个业务部门组织的数据库来保存数据。比如,随着数据量的增长,公司通常可能会构建数十个独立运行的业务数据库&am…...
【周输入】510周阅读推荐-1
本号一年了,有一定的成长,也有很多读者和点赞。自觉更新仍然远远不够,需要继续努力。 但是还是要坚持2点: 在当前这个时代,信息大爆炸,层次不齐,不追加多, 信息输入可以很多&#x…...
Games101作业四
作业0到作业3的代码 这次是实现 de Casteljau 算法,以及绘制 Bezier 曲线,比上次简单 核心思想就是递归,原理忘了就去看第十一节课,从15:00开始的 GAMES101-现代计算机图形学入门-闫令琪 代码 先实现贝塞尔曲线 cv::Point2f recursive_bezier(const std::…...
从Aurora 架构看数据库计算存储分离架构
单就公有云来说,现在云数据面临的挑战有以下 5 个: 跨 AZ 的可用性与数据安全性。 现在都提多 AZ 部署,亚马逊在全球有 40 多个 AZ, 16 个 Region,基本上每一个 Region 之内的那些关键服务都是跨 3 个 AZ。你要考虑整个…...
ElasticSearch深入解析(十一):分页
在Elasticsearch中,常用的分页方案有from size、search_after和scroll三种,适用于不同场景。from size基于偏移量分页,是全局排序后的切片查询,适用于小数据量、浅分页场景,但深度分页性能差,且有默认上限…...
【MySQL】MySQL数据库结构与操作
目录 一. 数据库的概念 二. 数据库的分类 三. 初始MySQL数据库 四. 数据库操作 1)创建数据库 2) 查看数据库 3)选中数据库 4)删除数据库 五. SQL数据类型 1)整型和浮点型 2)字符串类型 3)时间…...
Vue框架的基本介绍
目录 一.Vue 1.概述 2.三大主流框架 3.优点: 二.Vue搭建 三.语法 1.基本框架 2.插值表达式 3.Vue指令 1.v-text: 2.v-html: 编辑3.v-model: 4.v-on: 5.v-show: 6.v-if: 7.v-else: 8.v-bind: 9.v-for: 一.Vue 1.概述 Vue是一款用于构建用户界面的渐进式的…...
Web 架构之攻击应急方案
文章目录 一、引言二、常见 Web 攻击类型及原理2.1 SQL 注入攻击2.2 跨站脚本攻击(XSS)2.3 分布式拒绝服务攻击(DDoS) 三、攻击检测3.1 日志分析3.2 入侵检测系统(IDS)/入侵防御系统(IPS&#x…...
xss-labs靶场基础8-10关(记录学习)
前言: 内容: 第八关 关卡资源网站,html编码网站(两个网站,一个是实体编号转义(只对特殊字符有效,字母无效)、实体符号转义) 在线Html实体编码解码-HTML Entity Encodi…...
arctanx 导数 泰勒展开式证明
你提供的推导内容非常清晰,条理分明。下面是对 d d x arctan x 1 1 x 2 \frac{d}{dx} \arctan x \frac{1}{1 x^2} dxdarctanx1x21 的总结与适当补充: ✅ 结论 d d x arctan x 1 1 x 2 \frac{d}{dx} \arctan x \frac{1}{1 x^2} dxda…...
基于Java的家政服务平台设计与实现(代码+数据库+LW)
摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本家政服务平台就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息&a…...
SpringBoot的外部化配置
一、什么是外部化配置 外部化配置是指把应用程序中各种可配置的参数、属性等信息,从代码内部提取出来,放置在外部的配置文件、数据库或配置中心等地方(比如使用.properties、.yml 或.xml 等格式的文件)进行管理。提高应用程序的可…...
Java鼠标事件监听器MouseListener、MouseMotionListener和MouseWheelListener
Java鼠标事件监听器MouseListener、MouseMotionListener和MouseWheelListener java中创建鼠标,键盘的事件行为监听器的几种方法 这里以鼠标点击事件监听器为例,其他也是一样创建。 常用的消息监听器对象 1:点击事件监听器 ActionListener 2:按键事件监…...
第三方支付公司如何代付和入账?
通俗来说,就是企业把钱打到第三方公司账户上,再由第三方公司把钱打入客户指定账户。 那么第三方支付入账流程是怎样的呢? 第一,企业向第三方支付公司指定账户充值打款;第二,企业提交代付银行卡信息后台操…...
.NET8关于ORM的一次思考
文章目录 前言一、思路二、实现ODBC>SqlHelper.cs三、数据对象实体化四、SQL生成SqlBuilder.cs五、参数注入 SqlParameters.cs六、反射 SqlOrm.cs七、自定义数据查询八、总结 前言 琢磨着在.NET8找一个ORM,对比了最新的框架和性能。 框架批量操作性能SQL控制粒…...
LlamaIndex 第八篇 MilvusVectorStore
本指南演示了如何使用 LlamaIndex 和 Milvus 构建一个检索增强生成(RAG)系统。 RAG 系统将检索系统与生成模型相结合,根据给定的提示生成新的文本。该系统首先使用 Milvus 等向量相似性搜索引擎从语料库中检索相关文档,然后使用生…...
记录为什么LIst数组“增删慢“,LinkedList链表“查改快“?
数组(Array) 增删慢:对于数组来说,增加或删除元素的操作可能会比较慢,特别是当你需要在数组的开头或中间进行这些操作时。这是因为这些操作通常需要移动数组中的其他元素以保持连续性。例如,如果你想要在数…...
【论文阅读】Dip-based Deep Embedded Clustering with k-Estimation
摘要 近年来,聚类与深度学习的结合受到了广泛关注。无监督神经网络,如自编码器,能够自主学习数据集中的关键结构。这一思想可以与聚类目标结合,实现对相关特征的自动学习。然而,这类方法通常基于 k-means 框架&#x…...
ARFoundation 图片识别,切换图片克隆不同的追踪模型
场景搭建: 你可以把我的代码发给AI,去理解 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; using TMPro; using Unit…...
鸿蒙next播放B站视频横屏后的问题
(此文讨论范围为b站视频链接,且不包括b站直播链接;android/iOS的webview播放b站视频完全没有这么多问题) 1、竖屏播放没问题 从一个竖屏页p1点击进入视频页p2,p2页仍为竖屏; p2页有一Web组件,…...
华为0507机试
题目二 建设基站 有一棵二叉树,每个节点上都住了一户居民。现在要给这棵树上的居民建设基站,每个基站只能覆盖她所在与相邻的节点,请问信号覆盖这棵树最少需要建设多少个基站 #include <bits/stdc.h> using namespace std;const int …...
apache2的默认html修改
使用127.0.0.1的时候,默认打开的是index.html,可以通过配置文件修改成我们想要的html vi /etc/apache2/mods-enabled/dir.conf <IfModule mod_dir.c>DirectoryIndex WS.html index.html index.cgi index.pl index.php index.xhtml index.htm <…...
EXCEL下拉菜单与交替上色设置
Excel/WPS 表格操作教程(双功能整合) 目录 功能一:交替行上色 Excel 操作WPS 操作 功能二:下拉菜单设置 Excel 操作WPS 操作 组合效果示例注意事项 功能一:交替行上色 Excel 操作 选中数据区域 拖动鼠标选择需要设置…...
list基础用法
list基础用法 1.list的访问就不能用下标[]了,用迭代器2.emplace_back()几乎是与push_back()用法一致,但也有差别3.insert(),erase()的用法4.reverse()5.排序6.合并7.unique()(去重)8.splice剪切再粘贴 1.list的访问就不能用下标[]了,用迭代器…...