java日志框架之JUL(Logging)
文章目录
- 一、JUL简介
- 1、JUL组件介绍
- 二、Logger快速入门
- 三、Logger日志级别
- 1、日志级别
- 2、默认级别info
- 3、原理分析
- 4、自定义日志级别
- 5、日志持久化(保存到磁盘)
- 三、Logger父子关系
- 四、Logger配置文件
一、JUL简介
- JUL全程
Java Util Logging,它是java原生的日志框架,使用时不需要另外引用第三方的类库 - 相对其他的框架使用方便,学习简单,主要是使用在小型应用中
1、JUL组件介绍

- Logger:被称为记录器
- 应用程序通过获取Logger对象,调用其API来发布日志信息
- Logger通常被认为是访问日志系统的入口程序
- Handler:处理器
- 每个Logger都会关联一个或者是一组Handler
- Logger会将日志交给关联的Handler去做处理,由Handler负责将日志做记录
Handler具体实现了日志的输出位置,比如可以输出到控制台或者是文件中等等
- Filter:过滤器
- 根据需要定制哪些信息会
被记录,哪些信息会被略过
- 根据需要定制哪些信息会
- Formatter:格式化组件
- 它负责对日志中的数据和信息进行转换和格式化,所以它决定了我们
输出日志最终的形式
- 它负责对日志中的数据和信息进行转换和格式化,所以它决定了我们
- Level:日志的输出级别
- 每条日志消息都有一个关联的级别
- 我们根据输出级别的设置,用来展现最终所呈现的日志信息
- 根据不同的需求,去
设置不同的级别
总结
用户使用Logger来进行日志记录,Logger持有若干个Handler,日志的输出操作是由Handler完成的。在Handler在输出日志前,会经过Filter的过滤,判断哪些日志级别过滤放行哪些拦截,Handler会将日志内容输出到指定位置(日志文件、控制台等)。Handler在输出日志时会使用Layout,将输出内容进行排版。
二、Logger快速入门
import java.util.logging.Level;
import java.util.logging.Logger;public class JULTest {@Testpublic void test01() {// Logger对象的创建方式,不能直接new对象// 取得对象的方法参数,需要引入当前类的全路径字符串Logger logger = Logger.getLogger("com.xc.log.JULTest");// 第一种方式: 直接调用日志级别相关的方法,方法中传递日志输出信息logger.info("输出info信息1");// 第二种方式:调用通用的log方法,然后在里面通过Level类型来定义日志的级别参数,// 以及搭配日志输出信息的参数logger.log(Level.INFO, "输出info信息2");// 日志添加参数String name = "zs";int age = 23;logger.log(Level.INFO, "学生的姓名:{0},年龄: {1}", new Object[]{name, age});}
}
输出结果:
九月 17, 2024 5:45:30 下午 com.xc.log.JULTest test01
信息: 输出info信息1
九月 17, 2024 5:45:30 下午 com.xc.log.JULTest test01
信息: 输出info信息2
九月 17, 2024 5:45:30 下午 com.xc.log.JULTest test01
信息: 学生的姓名:zs,年龄: 23
三、Logger日志级别
1、日志级别
java.util.logging.Level中定义了日志的级别- SEVERE(最高值)
- WARNING
- INFO (默认级别)
- CONFIG
- FINE
- FINER
- FINEST(最低值)
- 还有两个特殊的级别
- OFF,可用来关闭日志记录
- ALL,启用所有消息的日志记录
public class Level implements java.io.Serializable {...//错误 --- 最高级的日志级别public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);//WARNING : 警告public static final Level WARNING = new Level("WARNING", 900, defaultBundle);//INFO : (默认级别)消息public static final Level INFO = new Level("INFO", 800, defaultBundle);//CONFIG : 配置public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);//FINE : 详细信息public static final Level FINE = new Level("FINE", 500, defaultBundle);//FINER : 较详细信息public static final Level FINER = new Level("FINER", 400, defaultBundle);//FINEST : 非常详细信息 --- 最低级的日志级别public static final Level FINEST = new Level("FINEST", 300, defaultBundle);//OFF 可用来关闭日志记录public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);//ALL 启用所有消息的日志记录public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);...
}
2、默认级别info
@Test
public void test02(){Logger logger = Logger.getLogger("com.xc.log.JULTest");//打印日志logger.severe("severe信息");logger.warning("warning信息");logger.info("info信息");logger.config("config信息");logger.fine("fine信息");logger.finer("finer信息");logger.finest("finest信息");
}
输出结果:
九月 17, 2024 6:36:00 下午 com.xc.log.JULTest test02
严重: severe信息
九月 17, 2024 6:36:00 下午 com.xc.log.JULTest test02
警告: warning信息
九月 17, 2024 6:36:00 下午 com.xc.log.JULTest test02
信息: info信息
3、原理分析
- 以SEVERE、WARNING、INFO级别为例
public class Logger {...// 严重错误public void severe(String msg) {log(Level.SEVERE, msg);}// 警告信息public void warning(String msg) {log(Level.WARNING, msg);}// 记录信息public void info(String msg) {log(Level.INFO, msg);}// 无论哪种类型都会进入此方法,只是传入不同的级别参数public void log(Level level, String msg) {// 判断日志级别是否需要打印if (!isLoggable(level)) {return;}LogRecord lr = new LogRecord(level, msg);doLog(lr);}// levelValue为默认级别Level.INFO的数值800// offValue为关闭日志级别Level.OFF的数值Integer.MAX_VALUEpublic boolean isLoggable(Level level) {if (level.intValue() < levelValue || levelValue == offValue) {return false;}return true;}
}
- levelValue为默认级别Level.INFO的数值800
大于等于800的SEVERE-1000、WARNING-900、INFO-800三个级别,isLoggable方法返回true,都可以输出- 当默认级别为
Level.OFF的数值Integer.MAX_VALUE,isLoggable方法返回false,都不可以输出 - 当默认级别为
Level.ALL的数值Integer.MIN_VALUE,isLoggable方法返回true,都可以输出
4、自定义日志级别
@Test
public void test03() {// 日志记录器Logger logger = Logger.getLogger("com.xc.log.JULTest");// 关闭系统默认配置logger.setUseParentHandlers(false);// 处理器Handler// 在此我们使用的是控制台日志处理器,取得处理器对象ConsoleHandler handler = new ConsoleHandler();// 在处理器中设置输出格式handler.setFormatter(new SimpleFormatter());// 在记录器中添加处理器logger.addHandler(handler);// 设置日志的打印级别// 此处必须将日志记录器和处理器的级别进行统一的设置,才会达到日志显示相应级别的效果logger.setLevel(Level.ALL); // 日志记录器handler.setLevel(Level.ALL); // 日志处理器logger.severe("severe信息");logger.warning("warning信息");logger.info("info信息");logger.config("config信息");logger.fine("fine信息");logger.finer("finer信息");logger.finest("finest信息");
}
输出结果:
九月 17, 2024 7:18:11 下午 com.xc.log.JULTest test03
严重: severe信息
九月 17, 2024 7:18:11 下午 com.xc.log.JULTest test03
警告: warning信息
九月 17, 2024 7:18:11 下午 com.xc.log.JULTest test03
信息: info信息
九月 17, 2024 7:18:11 下午 com.xc.log.JULTest test03
配置: config信息
九月 17, 2024 7:18:11 下午 com.xc.log.JULTest test03
详细: fine信息
九月 17, 2024 7:18:11 下午 com.xc.log.JULTest test03
较详细: finer信息
九月 17, 2024 7:18:11 下午 com.xc.log.JULTest test03
非常详细: finest信息
5、日志持久化(保存到磁盘)
- 用户使用Logger来进行日志的记录,
Logger可以持有多个处理器Handler - 日志的记录使用的是Logger,日志的输出使用的是Handler
- 可以输出到
控制台也可以输出到文件,也可以两者兼备
@Test
public void test04() throws IOException {Logger logger = Logger.getLogger("com.xc.log.JULTest");logger.setUseParentHandlers(false);// 文件日志处理器FileHandler handler = new FileHandler("/Users/xuchang/Documents/javaCode/data/logs/jul.log");SimpleFormatter formatter = new SimpleFormatter();handler.setFormatter(formatter);logger.addHandler(handler);// 也可以同时在控制台和文件中进行打印ConsoleHandler handler2 = new ConsoleHandler();handler2.setFormatter(formatter);// 可以在记录器中同时添加多个处理器logger.addHandler(handler2);// 设置日志的打印级别logger.setLevel(Level.ALL);// 输出到文件的级别为allhandler.setLevel(Level.INFO);// 输出到控制台的解绑为confighandler2.setLevel(Level.CONFIG);logger.severe("severe信息");logger.warning("warning信息");logger.info("info信息");logger.config("config信息");logger.fine("fine信息");logger.finer("finer信息");logger.finest("finest信息");
}
控制台config日志级别输出如下:

文件info日志级别输出如下:

三、Logger父子关系
- JUL中Logger之间存在
父子关系,这种父子关系通过树状结构存储 - JUL在初始化时会创建一个
顶层RootLogger作为所有Logger父Logger,存储上作为树状结构的根节点 - 父子关系通过
路径来关联
@Test
public void test05() {// 父亲是RootLogger,名称默认是一个空的字符串// RootLogger可以被称之为所有logger对象的顶层loggerLogger logger1 = Logger.getLogger("com.xc");Logger logger2 = Logger.getLogger("com.xc.log");Logger logger3 = Logger.getLogger("com.xc.log.JULTest");System.out.println("logger1的父Logger引用为:"+ logger1.getParent() + "; 名称为" + logger1.getName() + ";" +" 父亲的名称为" + logger1.getParent().getName());System.out.println("logger2的父Logger引用为:"+ logger2.getParent() + "; 名称为" + logger2.getName() + ";" +" 父亲的名称为" + logger2.getParent().getName());System.out.println("logger3的父Logger引用为:"+ logger3.getParent() + "; 名称为" + logger3.getName() + ";" +" 父亲的名称为" + logger3.getParent().getName());
}
输出结果:

父亲所做的设置,也能够同时作用于儿子
logger1是logger2的父级,父级logger1设置日志级别为ALL,即使子级什么也不设置(默认info级别),最后通过打印可看到,子级跟随父级已经设置为ALL。
@Test
public void test06() {Logger logger1 = Logger.getLogger("com.xc.log");Logger logger2 = Logger.getLogger("com.xc.log.JULTest");// 父亲设置级别为alllogger1.setUseParentHandlers(false);ConsoleHandler handler = new ConsoleHandler();SimpleFormatter formatter = new SimpleFormatter();handler.setFormatter(formatter);logger1.addHandler(handler);handler.setLevel(Level.ALL);logger1.setLevel(Level.ALL);// 儿子默认级别为infologger2.severe("severe信息");logger2.warning("warning信息");logger2.info("info信息");logger2.config("config信息");logger2.fine("fine信息");logger2.finer("finer信息");logger2.finest("finest信息");
}
输出结果:
九月 17, 2024 9:05:57 下午 com.xc.log.JULTest test06
严重: severe信息
九月 17, 2024 9:05:57 下午 com.xc.log.JULTest test06
警告: warning信息
九月 17, 2024 9:05:57 下午 com.xc.log.JULTest test06
信息: info信息
九月 17, 2024 9:05:57 下午 com.xc.log.JULTest test06
配置: config信息
九月 17, 2024 9:05:57 下午 com.xc.log.JULTest test06
详细: fine信息
九月 17, 2024 9:05:57 下午 com.xc.log.JULTest test06
较详细: finer信息
九月 17, 2024 9:05:57 下午 com.xc.log.JULTest test06
非常详细: finest信息
四、Logger配置文件
- 默认读取配置文件路径
$JAVAHOME\jre\lib\logging.properties
# 全局性质
############################################################
# RootLogger使用的处理器
handlers=java.util.logging.ConsoleHandler
# RootLogger日志等级
.level = INFO
############################################################# 处理器指定属性,描述处理程序的特定配置信息
############################################################
# 文件处理器属性设置
# 默认输出的日志文件路径,位于用户的主目录中
java.util.logging.FileHandler.pattern = %h/java%u.log
# 默认输出的日志文件大小(单位字节)
java.util.logging.FileHandler.limit = 50000
# 默认输出的日志文件数量
java.util.logging.FileHandler.count = 1
# 默认输出的日志文件格式(XML)
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter# 控制台处理器属性设置
# 默认输出的日志级别
java.util.logging.ConsoleHandler.level = INFO
# 默认输出的日志格式(Simple)
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
############################################################# 配置特定属性,为每个记录器提供额外的控制
############################################################
# 例如:将日志级别设定到具体的某个包下
com.xyz.foo.level = SEVERE
############################################################
- 自定义配置文件,将配置文件添加到resources目录下
@Test
public void test07() throws Exception {// 读取自定义配置文件InputStream in = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");// 获取日志管理器对象LogManager logManager = LogManager.getLogManager();// 通过日志管理器加载配置文件logManager.readConfiguration(in);Logger logger = Logger.getLogger("com.xc.log.JULTest");logger.severe("severe");logger.warning("warning");logger.info("info");logger.config("config");logger.fine("fine");logger.finer("finer");logger.finest("finest");
}
- 可以
忽略父级配置,添加自定义配置,设置默认日志级别、日志追加(默认覆盖)等
## RootLogger使用的处理器(获取时设置)
handlers=java.util.logging.ConsoleHandler
# RootLogger日志等级
.level=INFO## 自定义Logger
com.xc.handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
# 自定义Logger日志等级
com.xc.level=CONFIG
# 忽略父日志设置
com.xc.useParentHandlers=false## 控制台处理器
# 输出日志级别
java.util.logging.ConsoleHandler.level=CONFIG
# 输出日志格式
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter## 文件处理器
# 输出日志级别
java.util.logging.FileHandler.level=CONFIG
# 输出日志格式
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
# 输出日志文件路径
java.util.logging.FileHandler.pattern=/Users/xuchang/Documents/javaCode/data/logs/java%u.log
# 输出日志文件限制大小(50000字节)
java.util.logging.FileHandler.limit=50000
# 输出日志文件限制个数
java.util.logging.FileHandler.count=10
# 输出日志文件 是否是追加
java.util.logging.FileHandler.append=true
控制台日志

文件追加日志

相关文章:
java日志框架之JUL(Logging)
文章目录 一、JUL简介1、JUL组件介绍 二、Logger快速入门三、Logger日志级别1、日志级别2、默认级别info3、原理分析4、自定义日志级别5、日志持久化(保存到磁盘) 三、Logger父子关系四、Logger配置文件 一、JUL简介 JUL全程Java Util Loggingÿ…...
ARM驱动学习之PWM
ARM驱动学习之PWM 1.分析原理图: GPD0_0 XpwmTOUT0定时器0 2.定时器上的资源: 1.5组32位定时器 2.定时器产生内部中断 3.定时器0,1,2可编程实现pwm 4.定时器各自分频 5.TCN--,TCN TCMPBN 6.分频器 24-2 7.24.3.4 例子࿱…...
我的AI工具箱Tauri版-VideoClipMixingCut视频批量混剪
本教程基于自研的AI工具箱Tauri版进行VideoClipMixingCut视频批量混剪。 VideoClipMixingCut视频批量混剪 是自研AI工具箱Tauri版中的一款强大工具,专为自动化视频批量混剪设计。该模块通过将预设的解说文稿与视频素材进行自动拼接生成混剪视频,适合需要…...
postgres_fdw访问存储在外部 PostgreSQL 服务器中的数据
文章目录 一、postgres_fdw 介绍二、安装使用示例三、成本估算四、 远程执行选项执行计划无法递推解决 参考文件: 一、postgres_fdw 介绍 postgres_fdw 模块提供外部数据包装器 postgres_fdw,可用于访问存储在外部 PostgreSQL 服务器中的数据。 此模块…...
什么是3D展厅?有何优势?怎么制作3D展厅?
一、什么是3D展厅? 3D展厅是一种利用三维技术构建的虚拟展示空间。它借助虚拟现实(VR)、增强现实(AR)等现代科技手段,将真实的展示空间数字化,呈现出逼真、立体、沉浸的展示效果。通过3D展厅&a…...
Linux下的CAN通讯
CAN总线 CAN总线简介 CAN(Controller Area Network)总线是一种多主从式 <font color red>异步半双工串行 </font> 通信总线,它最早由Bosch公司开发,用于汽车电子系统。CAN总线具有以下特点: 多主从式&a…...
【Python】pip安装加速:使用国内镜像源
【Python】pip安装加速:使用国内镜像源 零、使用命令行设置 设置全局镜像源 随便使用下面任一命令即可! 阿里云: pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/豆瓣: pip config set global.in…...
SpringBoot lombok(注解@Getter @Setter)
SpringBoot lombok(注解Getter Setter) 使用lombok注解的方式,在编译生成的字节码文件中就会存在setter/getter等方法,减少代码量,方便了代码的维护 添加依赖 <dependency><groupId>org.projectlombok</groupId><artif…...
descrTable常用方法
descrTable 为 R 包 compareGroups 的重要函数,有关该函数以及 compareGroups 包的详细内容见:R包compareGroups详细用法 加载包和数据 library(compareGroups)# 加载 REGICOR 数据(横断面,从不同年份纳入,每个变量有…...
回归预测 | Matlab实现ReliefF-XGBoost多变量回归预测
回归预测 | Matlab实现ReliefF-XGBoost多变量回归预测 目录 回归预测 | Matlab实现ReliefF-XGBoost多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.ReliefF-xgboost回归预测代码,对序列数据预测性能相对较高。首先通过ReleifF对输入特征计算权…...
年度最强悬疑美剧重磅回归,一集比一集上头
纽约的夜晚,平静被一声枪响打破,一场离奇的谋杀案悄然上演。《大楼里只有谋杀》正是围绕这样一桩扑朔迷离的案件展开的。三位主角,赛琳娜戈麦斯饰演的梅宝、史蒂夫马丁饰演的查尔斯、马丁肖特饰演的奥利弗,这些性格迥异的邻居因为…...
AI一点通: 简化大数据与深度学习工作流程, Apache Spark、PyTorch 和 Mosaic Streaming
在大数据和机器学习飞速发展的领域中,数据科学家和机器学习工程师经常面临的一个挑战是如何桥接像 Apache Spark 这样的强大数据处理引擎与 PyTorch 等深度学习框架。由于它们在架构上的固有差异,利用这两个系统的优势可能令人望而生畏。本博客介绍了 Mo…...
Python知识点:深入理解Python的模块与包管理
开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 深入理解Python的模块与包管理 Python的模块和包是代码组织、复用和分发的基本…...
倒排索引(反向索引)
倒排索引(Inverted Index)是搜索引擎和数据库管理系统中常用的一种数据结构,用于快速检索文档集合中的文档。在全文搜索场景中,倒排索引是一种非常高效的手段,因为它能够快速定位到包含特定关键词的所有文档。 1、基本…...
openCV的python频率域滤波
在OpenCV中实现频率域滤波通常涉及到傅里叶变换(Fourier Transform)和其逆变换(Inverse Fourier Transform)。傅里叶变换是一种将图像从空间域转换到频率域的数学工具,这使得我们可以更容易地在图像的频域内进行操作,如高通滤波、低通滤波等。 下面,我将提供一个使用Py…...
探索视频美颜SDK与直播美颜工具的开发实践方案
直播平台的不断发展,让开发出性能优异、效果自然的美颜技术,成为了技术团队必须面对的重要挑战。本篇文章,小编将深入讲解视频美颜SDK与直播美颜工具的开发实践方案。 一、视频美颜SDK的核心功能 视频美颜SDK是视频处理中的核心组件…...
Linux通过yum安装Docker
目录 一、安装环境 1.1. 旧的docker包卸载 1.2. 安装常规环境包 1.3. 设置存储库 二、安装Docker社区版 三、解决拉取镜像失败 3.1. 创建文件目录/etc/docker 3.2. 写入镜像配置 https://docs.docker.com/engine/install/centos/ 检测操作系统版本,我操作的…...
面部表情数据集合集——需要的点进来
文章目录 1、基本介绍2、每个数据集介绍2.1、FER2013(已预处理)2.2、FERPLUS(已预处理)2.3、RAF2.4、CK2.5、AffectNet2.6、MMAFEDB 3、获取方式 1、基本介绍 收集并整理了面部表情识别(Facial Emotion Recognition&am…...
AI学习指南深度学习篇-Adagrad的Python实践
AI学习指南深度学习篇-Adagrad的Python实践 在深度学习领域,优化算法是模型训练过程中至关重要的一环。Adagrad作为一种自适应学习率优化算法,在处理稀疏梯度和非凸优化问题时表现优异。本篇博客将使用Python中的深度学习库TensorFlow演示如何使用Adagr…...
vue2使用npm引入依赖(例如axios),报错Module parse failed: Unexpected token解决方案
报错情况 Module parse failed: Unexpected token (5:2) You may need an appropriate loader to handle this file type. 原因 因为我们npm install时默认都是下载最新版本,然后个别依赖的版本太新,vue2他受不起这个福分。 解决方法 先去package.js…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
