JDK 9 模块化系统 (Module System) 和 多版本兼容 Jar (Multi-Release Jar)

news2024/12/26 22:15:40

博文目录

文章目录

  • Module System
    • 原因
    • JDK 模块化
    • 模块描述文件
      • 关键字
    • 启用模块化
    • 测试
    • 结论
  • Multi-Release jar (MRJAR)
    • 原因
    • 原理
    • 结论
    • 用 IDEA 创建多版本兼容 Jar
      • 项目结构
      • pom.xml
      • 测试


Module System

原因

Java 9引入了模块化系统的主要原因是为了解决Java平台面临的复杂性和可维护性方面的挑战。以下是一些采用模块化系统的主要原因:

  • 更好的代码组织:传统的Java应用程序通常由大量的JAR文件组成,这些JAR文件之间的依赖关系可能变得非常复杂。模块化系统允许开发人员将代码组织为模块,将相关的类和资源放在一起,使代码更易于理解和维护。模块化还提供了更细粒度的可见性和封装,使开发人员能够更好地控制代码的可访问性。
  • 更好的可重用性:模块化系统鼓励开发人员将功能划分为独立的模块,这些模块可以在不同的项目中重复使用。通过明确声明模块之间的依赖关系,模块化系统提供了更好的可重用性和解耦性。
  • 更好的性能和安全性:模块化系统允许JVM在运行时仅加载所需的模块,而不是加载整个类路径上的所有类。这可以提高应用程序的启动时间和内存利用率。此外,模块化系统通过明确声明模块之间的依赖关系,可以提供更好的安全性,防止不受信任的代码访问和修改模块之间的内部实现。
  • 改进的可扩展性:模块化系统引入了明确的导出和使用规范,使开发人员能够更好地定义模块之间的接口和依赖关系。这使得应用程序的功能可以更容易地进行扩展和定制,同时保持模块之间的清晰界限。

总的来说,Java 9的模块化系统提供了一种更好的方式来组织、重用和管理Java代码,改善了传统的类路径模型面临的复杂性和可维护性问题。它提供了更好的可见性、封装性、性能、安全性和可扩展性,从而改进了Java开发的体验和应用程序的质量。

JDK 模块化

自 Java 9 起, JDK 自身也被模块化, 按照功能划分为一系列有依赖关系的模块

  • java.base: 核心模块, 最基础模块, 其他模块都会依赖到它. 包含基本类库和运行时环境, 如 Object, String, 集合框架, 输入输出, 并发工机具等, 是构建 Java 应用程序的基础
  • java.se: 这个模块表示 Java 标准版 (Java SE). 它是一个聚合模块 (只有模块描述文件 module-info.java), 其中引入了许多常用的模块, 包含了大部分 Java SE 规范中定义的 API. 就相当于以前的 rt.jar
# 查看模块列表
java --list-modules
# 查看模块信息 (module-info.java)
java -d <模块名称>
java --describ-module <模块名称>

以下是 JDK 11.0.20 的模块列表

> java --list-modules
java.base@11.0.20
java.compiler@11.0.20
java.datatransfer@11.0.20
java.desktop@11.0.20
java.instrument@11.0.20
java.logging@11.0.20
java.management@11.0.20
java.management.rmi@11.0.20
java.naming@11.0.20
java.net.http@11.0.20
java.prefs@11.0.20
java.rmi@11.0.20
java.scripting@11.0.20
java.se@11.0.20
java.security.jgss@11.0.20
java.security.sasl@11.0.20
java.smartcardio@11.0.20
java.sql@11.0.20
java.sql.rowset@11.0.20
java.transaction.xa@11.0.20
java.xml@11.0.20
java.xml.crypto@11.0.20
jdk.accessibility@11.0.20
jdk.attach@11.0.20
jdk.charsets@11.0.20
jdk.compiler@11.0.20
jdk.crypto.cryptoki@11.0.20
jdk.crypto.ec@11.0.20
jdk.crypto.mscapi@11.0.20
jdk.dynalink@11.0.20
jdk.editpad@11.0.20
jdk.hotspot.agent@11.0.20
jdk.httpserver@11.0.20
jdk.internal.ed@11.0.20
jdk.internal.jvmstat@11.0.20
jdk.internal.le@11.0.20
jdk.internal.opt@11.0.20
jdk.internal.vm.ci@11.0.20
jdk.internal.vm.compiler@11.0.20
jdk.internal.vm.compiler.management@11.0.20
jdk.jartool@11.0.20
jdk.javadoc@11.0.20
jdk.jcmd@11.0.20
jdk.jconsole@11.0.20
jdk.jdeps@11.0.20
jdk.jdi@11.0.20
jdk.jdwp.agent@11.0.20
jdk.jfr@11.0.20
jdk.jlink@11.0.20
jdk.jshell@11.0.20
jdk.jsobject@11.0.20
jdk.jstatd@11.0.20
jdk.localedata@11.0.20
jdk.management@11.0.20
jdk.management.agent@11.0.20
jdk.management.jfr@11.0.20
jdk.naming.dns@11.0.20
jdk.naming.ldap@11.0.20
jdk.naming.rmi@11.0.20
jdk.net@11.0.20
jdk.pack@11.0.20
jdk.rmic@11.0.20
jdk.scripting.nashorn@11.0.20
jdk.scripting.nashorn.shell@11.0.20
jdk.sctp@11.0.20
jdk.security.auth@11.0.20
jdk.security.jgss@11.0.20
jdk.unsupported@11.0.20
jdk.unsupported.desktop@11.0.20
jdk.xml.dom@11.0.20
jdk.zipfs@11.0.20

以下是 JDK 11.0.20 中, 聚合模块 java.se 的模块描述信息, 里面全是可传递的 requires

> java -d java.se
java.se@11.0.20
requires java.rmi transitive
requires java.management.rmi transitive
requires java.base mandated
requires java.instrument transitive
requires java.desktop transitive
requires java.transaction.xa transitive
requires java.security.jgss transitive
requires java.management transitive
requires java.prefs transitive
requires java.security.sasl transitive
requires java.xml transitive
requires java.sql transitive
requires java.naming transitive
requires java.datatransfer transitive
requires java.xml.crypto transitive
requires java.logging transitive
requires java.compiler transitive
requires java.scripting transitive
requires java.sql.rowset transitive
requires java.net.http transitive

模块描述文件

模块描述文件(module-info.java)是 Java 模块化系统中的一个特殊文件,用于定义和配置模块的属性,依赖关系和访问控制

  • 文件位置:模块描述文件位于模块的根目录下(源码目录下,Maven 项目的源码文件夹通常是 src/main/java 中的 java 文件夹),并以 module-info.java 作为文件名
  • 文件格式:模块描述文件是一个普通的 Java 源代码文件,使用 Java 编程语言的语法和结构进行编写
  • 模块声明:模块描述文件以 module 关键字开头, 后跟模块的名称. 例如 module com.example.moduleName {}

关键字

  • module:在模块描述文件(module-info.java)中,使用 “module” 关键字定义一个Java模块。模块是一组相关的类和资源的集合,具有明确的依赖关系和访问控制
  • requires:使用 “requires” 关键字在模块描述文件中声明一个模块依赖于其他模块。例如,模块 A 可以声明 “requires B;”,表示模块 A 依赖于模块 B。
    • transitive:当一个模块(例如模块A)依赖于另一个模块(例如模块B)时,可以在 “requires” 语句中使用 “transitive” 关键字。例如,模块 A 可以声明 “requires B transitive;”,这意味着除了模块 A 直接依赖于模块 B 之外,任何依赖于模块 A 的模块也将隐式地依赖于模块 B。这样的传递性依赖关系可以简化模块之间的依赖管理。
  • exports:使用 “exports” 关键字在模块描述文件中声明一个模块的包对其他模块可见。通过 “exports” 语句,可以将模块的公共 API 公开给其他模块使用。例如,模块 A 可以声明 “exports com.example.package;”,表示模块 A 将其名为 com.example.package 的包对其他模块可见。
  • opens:与 “exports” 类似,“opens” 关键字也用于在模块描述文件中声明一个模块的包对其他模块可见。然而,与 “exports” 不同的是,“opens” 关键字还允许其他模块通过反射访问该包中的非公共类型。例如,模块 A 可以声明 “opens com.example.package;”,这样其他模块可以通过反射访问 com.example.package 包中的非公共类型。需要与 “exports” 一起使用, 两者合起来才是完整的权限
  • uses:使用 “uses” 关键字在模块描述文件中声明一个模块使用某个服务接口。这表示该模块需要在运行时从其他模块中获取实现该服务接口的提供者。例如,模块 A 可以声明 “uses com.example.ServiceInterface;”,表示模块 A 需要使用 com.example.ServiceInterface 这个服务接口。
  • provides:使用 “provides” 关键字在模块描述文件中声明一个模块提供某个服务接口的实现。这表示该模块是服务接口的一个提供者。例如,模块 A 可以声明 “provides com.example.ServiceInterface with com.example.ServiceImpl;”,表示模块 A 提供了com.example.ServiceInterface 接口的实现 com.example.ServiceImpl。
  • to:与 “provides” 关键字一起使用,指定一个或多个使用该服务接口的模块。例如,模块 A 可以声明 “provides com.example.ServiceInterface with com.example.ServiceImpl to moduleB, moduleC;”,表示模块 A 提供的 com.example.ServiceInterface实现将供模块 B 和模块 C 使用。

启用模块化

  • JDK 9 及以上
  • 添加模块描述文件 module-info.java

测试

生成一个模块化项目, 做一个工具类, 打包安装到 Maven 本地仓库, 用另一个普通项目依赖该 Jar 做测试, 将普通项目改成模块化项目做测试

结论

  • 非模块化项目可以依赖模块化的 Jar
  • 模块化的项目依赖非模块化的 Jar 则比较麻烦
    • 需要手动修改 Jar 的 MANIFEST.MF, 通过 Automatic-Module-Name 属性指定模块名(文件名), 将普通 Jar 修改为隐式模块, 然后通过 requires 引用
  • 由于很多第三方 Jar 都没有做模块化适配, 且模块化的项目依赖其他普通 Jar 的时候会比较麻烦, 所以暂不推荐搭建模块化项目, 这样就可以直接使用非模块化 Jar 和模块化 Jar
    • 如果依赖的第三方 Jar 都是模块化的, 那还是推荐把项目改成模块化项目, 可战未来

Multi-Release jar (MRJAR)

JEP 238: Multi-Release JAR Files

原因

Creating Multi-Release JAR Files in IntelliJ IDEA

在过去,库开发人员在支持较新版本的 Java 时有三种选择:

  • 提供两个(或更多!)不同的JAR文件,每个JAR文件对应于他们想要支持的Java版本。这些可能带有版本号,如“1.2-java-5”和“1.2-java-1.3”。
  • 将您的每一个版本都绑定到特定版本的Java,迫使用户要么升级他们的Java版本,要么停留在旧版本的库中。例如,“5.0版以后的版本需要Java 8”。
  • 坚持为用户发布最低公分母版本。对于许多库开发人员来说,这意味着他们仍然是根据Java 6进行编译的,并且在几乎所有用户都已经迁移到Java 8之前,不能迁移到使用Java 8的功能,如lambdas和流。
    • "最低公分母版本"是指在开发和发布软件时所考虑的目标用户群体中所使用的最旧版本的共同特性或功能子集。这意味着开发人员会选择支持最旧的、被广泛采用的版本,以确保尽可能多的用户能够使用他们的软件。

对于库开发人员或用户来说,这些方法都不是特别有趣。它们要么涉及大量工作,要么疏远/混淆用户,要么库无法利用新功能(因此也没有给用户提供太多升级Java版本的动力)。

从Java 9开始,还有一种选择。现在,库开发人员可以发布一个JAR文件,该文件:

  • 如果您在Java 9上运行它,请使用Java 9的特性和功能
  • 如果您在Java 9之前的版本上运行它,那么您将获得Java 9之前版本的实现。

这适用于Java 9以后的版本——因此这些多版本JAR文件将支持Java 9版本、Java 10(或18.3)、11、12版本等……但Java 9之前的任何内容都被归为“Java 9之前”。这有点令人难过,因为显然Java 8有一些不错的功能,如果你运行Java 8,你可能会想要这些功能,但Java 9之前对库的支持可能会像许多库一样,以Java6为目标,Java 8本身无法决定在运行多版本JAR文件时要做什么,因为该功能仅在Java 9中可用。

原理

root
	- A.class
	- B.class
	- C.class
	- D.class
	- META-INF
		- MANIFEST.MF
		- versions
     		- 9
     			- A.class
     			- B.class
   			- 11
   				- B.class

基本上,您有一个标准的JAR文件,像往常一样,在根目录中包含应用程序中的所有类,在META-INF中还有一个额外的 “versions” 文件夹,其中包含每个额外支持的Java版本的特定实现(在本例中,只有Java 9)。这个“9”文件夹只需要包含那些具有特定Java 9功能的类的类文件。如果不存在类(例如C.class),则将使用默认版本。

翻译成人话就是说, Java 9 在现有 Jar 结构的基础上扩展了 versions 机制, 如果使用 Java 6/7/8, 会使用到 root 下的 A/B/C/D 类, 如果使用 Java 9, 则会使用到 root/META-INF/versions/9 下的 A/B 类和 root 下的 C/D 类, 如果使用 Java 10, 和 Java 9 的情况一样, 如果使用 Java 11, 则会使用到 root/META-INF/versions/11 下的 B 类, root/META-INF/versions/9 下的 A 类, 还有 root 下的 C/D 类

只要将 Jar 包各部分用指定的 JDK 编译, 然后按照上述规范打包, 在 MANIFEST.MF 中额外指定 Multi-Release: true, 那么这个 Jar 就是一个多版本兼容 Jar 了, 在不同的 Java 环境下, 会自动选择合适版本的类. 这里有一个隐藏规范, 就是多个版本的类的 API 需要完全一致, 这个不是必须, 但是建议一致, 不然在使用中可能会出问题

结论

是一种好方法, 推荐开发库时使用

Java多版本兼容JAR的好处主要有以下几点:

  • 平滑迁移:Java多版本兼容JAR使得开发人员在升级Java版本时能够平滑迁移他们的应用程序。通过使用兼容的JAR文件,可以确保应用程序在不同版本的Java运行时环境中都能正常运行,而无需对现有的代码进行重写或修改。
  • 扩展用户基础:通过使用多版本兼容JAR,开发人员可以支持广泛的用户群体,包括那些仍在使用较旧Java版本的用户。这使得应用程序能够覆盖更多的用户,并且不会因为某些用户无法升级到最新Java版本而失去潜在的用户和市场份额。
  • 提高可靠性和稳定性:多版本兼容JAR可以提高应用程序的可靠性和稳定性。通过确保应用程序在不同Java版本上的兼容性,可以降低因为Java版本升级而引入的潜在兼容性问题和错误。
  • 简化部署和维护:Java多版本兼容JAR使得应用程序的部署和维护更加简化。开发人员只需提供一个通用的JAR文件,而不需要为每个Java版本提供单独的构建或分发。这简化了应用程序的构建、部署和维护流程,并减少了潜在的错误和混乱。
  • 充分利用新功能:多版本兼容JAR使得开发人员能够利用每个Java版本引入的新功能和改进。通过将新功能包装在兼容的JAR中,开发人员可以将这些功能提供给那些使用较新Java版本的用户,而无需牺牲对较旧Java版本的兼容性。

总的来说,Java多版本兼容JAR提供了一种灵活和可靠的方式,使得Java应用程序能够在各种不同版本的Java运行时环境中运行,并且能够充分利用每个版本的新功能。这为开发人员提供了更大的灵活性、更广泛的用户覆盖范围和更简化的部署维护流程。

用 IDEA 创建多版本兼容 Jar

Creating Multi-Release JAR Files in IntelliJ IDEA
Java SE 9 多版本兼容 JAR 包示例, 两个例子应该都没有使用 IDEA, 可以参考

Maven 支持在一个模块中创建两个源码文件夹, 并设置编辑级别, 以此来编译并打包, 但是在 IDEA 中, 同一个模块只能设置一个编辑级别, 且两个源码文件夹中不允许有完全相同的包和类. 用 IDEA 构建 Multi-Release Jar 需要忍受几个点, 一是不能按照源码文件夹设置语言级别(开发时无对应语言级别检查), 二是两个完全相同的类会报重复错误(不能直接运行测试). 其他的使用 IDEA 的 Maven 插件就可以搞定了

项目结构

新建一个 Maven 项目, JDK 选一个高版本的, 这里是 21.0.1, 项目结构如下, java 源码包用 8 编译, java.11 源码包用 11 编译

在这里插入图片描述

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.coder</groupId>
    <artifactId>demo.multi.release.jar</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <executions>
                    <execution>
                        <!--覆盖默认阶段和目标绑定的配置-->
                        <id>default-compile</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <!--从 JDK 9 起, 使用 release 替代 source 和 target, 因为后者不能保证代码在使用指定版本的JDK编译, 具体可参考下面两个链接-->
                            <!-- https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-release.html -->
                            <!-- https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html -->
                            <release>8</release>
                            <compileSourceRoots>
                                <compileSourceRoot>${project.basedir}/src/main/java</compileSourceRoot>
                            </compileSourceRoots>
                        </configuration>
                    </execution>
                    <execution>
                        <id>compile-java-11</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <release>11</release>
                            <compileSourceRoots>
                                <compileSourceRoot>${project.basedir}/src/main/java.11</compileSourceRoot>
                            </compileSourceRoots>
                            <outputDirectory>${project.build.outputDirectory}/META-INF/versions/11</outputDirectory>
                        </configuration>
                    </execution>
                    <execution>
                        <!--覆盖默认阶段和目标绑定的配置-->
                        <id>default-testCompile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                        <configuration>
                            <skip>true</skip>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Multi-Release>true</Multi-Release>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

测试

新建一个 java maven 项目, 分别设置项目 SDK 版本为 8/11/21 等, 查看输出内容, 查看 class 文件内容

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

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

相关文章

12 月 10 日,融云在 Google DevFest 上海站等你!

Welcome to DevFest!RongCloud2023 Google DevFest 上海站关注【融云全球互联网通信云】了解更多 时间&#xff1a;2023 年 12 月 10 日&#xff08;周日&#xff09;地点&#xff1a;上海市浦东新区新金桥路 1599 号&#xff0c;东方万国宴会中心 (下沉式广场)主讲&#xff1a…

反序列化漏洞详解(二)

目录 pop链前置知识&#xff0c;魔术方法触发规则 pop构造链解释&#xff08;开始烧脑了&#xff09; 字符串逃逸基础 字符减少 字符串逃逸基础 字符增加 实例获取flag 字符串增多逃逸 字符串减少逃逸 延续反序列化漏洞(一)的内容 pop链前置知识&#xff0c;魔术方法触…

etcd 与 Consul 的一致性读对比

本文分享和对比了 etcd 和 Consul 这两个存储的一致性读的实现。 作者&#xff1a;戴岳兵&#xff0c;爱可生研发中心工程师&#xff0c;负责项目的需求开发与维护工作。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 本…

vue 过滤器 (filters) ,实际开发中的使用

在实际开发中要判断不同的状态,要写很多重复的代码, 类似这样: 这样学麻烦, 不方便维护, 这时候可以用 filters 过滤器 在页面这样写就可以了

(04730)电路分析基础之基尔霍夫定律

基尔霍夫定律包括基尔霍夫电流定律(KCL)和基尔霍夫电压定律(KVL)。它反映了电路 中所有支路电压和电流所遵循的基本规律&#xff0c;是分析电路的基本定律。基尔霍夫定律与元件 特性构成了电路分析的基础。 电路是由电路元件按照一定的方式组成的系统&#xff0c;因此整个电路…

数据库增删改查(CRUD)进阶版

目录 数据库约束 约束类型 表的设计 1.一对一 2.一对多 3.多对多 增删查改进阶操作 1. 插入查询结果 2.查询 聚合查询 聚合函数 group by having 联合查询 内连接 外连接 自连接 子查询 合并查询 数据库约束 创建表的时候制定的一些规则&#xff0c;在后续…

字符串相似度匹配算法_莱茵斯坦距离算法

package day0330;public class LevenshteinDistanceUtil {public static void main(String[] args) {String a "WN64 F98";String b "WN64 F98 ";System.out.println("相似度:" getSimilarityRatio(a, b));}/*** 获取两字符串的相似度* * par…

MinIo 的操作与使用和避坑

文章目录 一、介绍二、安装三、Client 连通与避坑1. SpringBoot 项目2. 自己的 Maven 项目&#xff08;非 SpringBoot 项目&#xff09;思路1&#xff1a;尝试从 Maven 仓库中替换该 jar 包思路2&#xff1a;改造有问题的 jar 包 四、封装一些简单的方法 官方 API 文档&#xf…

阿里云域名解析到非默认端口处理方式

1.需配置两条解析记录&#xff0c;如下图 2.第一条配置A记录&#xff0c;ip指向部署服务器 3.第二条配置隐形记录&#xff0c;指向第一条的网址&#xff0c;并附带端口号&#xff0c;最终访问第二条的网址就不用带非默认端口号了。 4.最终浏览器访问

腾讯云轻量应用服务器挂载对象存储新手入门教程

腾讯云轻量对象存储LighthouseCOS是腾讯云专为中小企业开发者打造的轻量级数据存储服务&#xff0c;适用于云端网站、小程序、课堂演示、云盘/图床等场景下的数据存储和处理任务。腾讯云百科txybk.com详细介绍腾讯云轻量对象存储使用、开通和收费价格说明&#xff1a; 轻量对象…

家用超声波清洗机哪个牌子好?一起来看、值得推荐超声波清洗机

家用超声波清洗机可以干嘛呢&#xff1f;最常见的就是来清洗眼镜。眼镜党朋友应该经常接触超声波清洗机&#xff0c;它常出现在眼镜店中&#xff0c;眼镜店老板帮顾客清洗眼镜&#xff1b;也会出现在工业领域、医疗领域等&#xff0c;超声波清洗机使用范围还是挺广的&#xff0…

MIT6S081-Lab2总结

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com&#xff0c;github地址为https://github.com/xjintong。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 Lab2就是了解一下xv6的系统调用流程&…

Beam Search学习

BackGround 在生成的时候&#xff0c;模型的输出是一个时间步一个时间步依次获得的&#xff0c;而且前面时间步的结果还会影响后面时间步的结果。也就是说&#xff0c;每一个时间步&#xff0c;模型给出的都是基于历史生成结果的条件概率。 为了生成完整的句子&#xff0c;需…

Leetcode—2477.到达首都的最少油耗【中等】

2023每日刷题&#xff08;五十&#xff09; Leetcode—2477.到达首都的最少油耗 算法思想 参考自灵茶山艾府 实现代码 class Solution { public:long long minimumFuelCost(vector<vector<int>>& roads, int seats) {int n roads.size() 1;vector<i…

【开源】基于JAVA的桃花峪滑雪场租赁系统

项目编号&#xff1a; S 036 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S036&#xff0c;文末获取源码。} 项目编号&#xff1a;S036&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设…

打工人副业变现秘籍,某多/某手变现底层引擎-Stable Diffusion写好提示词

Stable Diffusion 是一种文生图 AI 模型,由互联网上数百万图像和文本描述对训练而来,通过理解文本描述与图像信息的内在关联,不断利用扩散过程进而得到满意的生成图片。 比如,通过一串提示词,midjourney 会输出这样的情侣合照: A pair of young Chinese lovers, wearing…

Docker部署.NET6项目

Docker的三大核心概念 1、docker仓库&#xff08;repository&#xff09; docker仓库&#xff08;repository&#xff09;类似于代码库&#xff0c;是docker集中存放镜像的场所。实际上&#xff0c;注册服务器是存放仓库的地方&#xff0c;其上往往存放着很多仓库。每个仓库集…

C++学习之路(十五)C++ 用Qt5实现一个工具箱(增加16进制颜色码转换和屏幕颜色提取功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《Base64图片编码预览功能》功能。为了继续丰富我们的工具箱&#xff0c;今天我们就再增加两个平时经常用到的功能吧&#xff0c;就是「 16进制颜色码转RGB文本 」和 「屏幕颜色提取」功能。下面我们就来看看如何来规划…

Postman可以卸载了!这款IDEA插件太好用了!

Postman是大家最常用的API调试工具&#xff0c;那么有没有一种方法可以不用手动写入接口到Postman&#xff0c;即可进行接口调试操作&#xff1f;今天给大家推荐一款IDEA插件&#xff1a;Apipost Helper&#xff0c;写完代码就可以调试接口并一键生成接口文档&#xff01;而且还…

C++笔试题之回文数的判断

“回文”是指正读反读都能读通的句子&#xff0c;它是古今中外都有的一种修辞方式和文字游戏&#xff0c;如“我为人人&#xff0c;人人为我”等。在数学中也有这样一类数字有这样的特征&#xff0c;成为回文数&#xff08;palindrome number&#xff09;。 设n是一任意自然数…