解锁编程的新契机:深入探讨Kotlin Symbol Processor (KSP)的编写

解锁编程的新契机:深入探讨Kotlin Symbol Processor (KSP)的编写

1. 引言

随着软件开发领域的不断发展,新的工具和技术不断涌现,以满足开发者在构建高效、可维护和创新性的代码方面的需求。Kotlin Symbol Processor(KSP)作为一项创新性的技术趋势,正在引起开发者们的广泛关注。本文将深入探讨Kotlin Symbol Processor(以下简称KSP)的背景、功能和应用,帮助读者了解其在Kotlin编程中的作用以及为什么它正在成为编程领域的新宠。

KSP是一种在编译期处理符号的工具,与Kotlin Annotation Processing Tool(KAPT)相似,但也有其独特之处。它能够更加高效地处理注解,生成代码,并提供更好的性能。在本文中,我们将探讨KSP的基本概念、与KAPT的比较、以及如何编写和应用KSP处理器,以便读者对其有一个全面的了解。

在接下来的章节中,我们将深入探讨KSP的各个方面,带您逐步了解这项新技术的工作原理、核心功能以及未来可能的发展趋势。通过本文,我们希望能够激发您对KSP的兴趣,并为您在Kotlin编程中的创造性工作提供新的思路和工具。

2. 什么是Kotlin Symbol Processor (KSP)

Kotlin Symbol Processor,简称KSP,是一种新兴的编译时处理工具,专为Kotlin编程语言设计。它在编译阶段与Kotlin编译器紧密集成,提供了一种高效、灵活的方式来处理代码中的符号(Symbols),如类、函数、属性和注解等。KSP的主要目标是提供一种更快速、更可靠、更高性能的方式来进行代码生成、分析和转换,以支持在编译期间进行更多的元编程和自动化操作。

基本概念和定义

在KSP中,"符号"是指源代码中的各种实体,例如类、函数、属性、参数、注解等。KSP允许开发者编写处理器(Processors),用于在编译时检查、操作和生成与这些符号相关的信息。这些处理器在编译过程中分析源代码,并基于代码结构和注解等信息,生成新的代码、报告问题或执行其他定制化操作。

KSP作为Kotlin编译器的插件

KSP是作为Kotlin编译器的插件而存在的,它利用了Kotlin编译器的内部机制,可以直接访问编译器的符号表和抽象语法树。这使得KSP可以更快速地处理符号,并且能够与Kotlin的类型系统和语法进行无缝集成。与传统的Annotation Processing Tool(APT)相比,KSP在性能、灵活性和开发体验方面都具有明显的优势。

KSP的作用

KSP的主要作用是增强Kotlin编程体验,使开发者能够更好地利用编译时的信息来进行代码生成和分析。通过在编译期进行操作,可以避免运行时的错误和性能问题,并提供更高质量的代码。KSP广泛用于以下方面:

  1. 代码生成: 开发者可以编写KSP处理器,根据注解或代码结构生成额外的代码,从而减少手动的重复工作。

  2. 元编程: KSP允许在编译时操作和检查代码本身,使得开发者可以实现更高级的元编程和代码分析。

  3. 自动化: 通过在编译期间对代码进行分析和处理,KSP可以自动执行一些常见的任务,如自动生成代码、生成文档等。

  4. 性能优化: KSP可以用于优化代码,例如消除不必要的依赖、生成高效的数据结构等。

总之,Kotlin Symbol Processor是Kotlin生态系统中的一项重要技术,为开发者提供了更强大的工具来进行元编程和代码自动化,从而提升了Kotlin应用的质量和性能。在接下来的章节中,我们将深入探讨KSP的工作原理、使用方法以及实际示例。

3. KSP与KAPT的比较

Kotlin Symbol Processor(KSP)和Kotlin Annotation Processing Tool(KAPT)都是用于在Kotlin编译时处理代码的工具,但它们在性能、功能扩展性和开发体验等方面存在一些差异。在本节中,我们将对比这两者的异同,重点介绍KSP相较于KAPT的优势。

相似之处

KSP和KAPT都属于编译时代码处理的范畴,它们可以用于生成、修改和分析代码。它们都通过处理注解和代码结构来实现代码生成和自动化操作。无论是KSP还是KAPT,都可以在编译阶段检查代码中的问题,生成新的代码文件,或者根据注解进行自定义逻辑。

性能比较

一项主要的差异是性能。KAPT使用的是基于Java的Annotation Processing Tool(APT),它在处理大量代码时可能会变得较慢,尤其是在较大项目中。与之不同,KSP在性能方面表现更出色。KSP充分利用了Kotlin编译器的内部机制,可以避免许多KAPT可能遇到的性能问题。这使得KSP在大型项目中处理符号更加高效,从而加速了编译过程。

功能扩展性

另一个区别在于功能扩展性。KSP提供了更灵活的方式来处理符号。它能够访问Kotlin编译器的内部API,允许开发者更深入地操作代码的符号表和抽象语法树。这意味着KSP处理器可以实现更多种类的操作,从简单的代码生成到复杂的代码分析。相比之下,KAPT的功能受到一定限制,无法与KSP在灵活性和功能上相媲美。

开发体验

KSP也提供了更好的开发体验。它更加集成化,无需额外的插件或配置,使得使用KSP变得更加简单和直接。另外,KSP处理器的错误信息和调试信息更易于理解,有助于开发者更快速地定位和解决问题。

总结KSP的优势

综上所述,KSP在性能、功能扩展性和开发体验等方面相对于KAPT具有明显的优势。KSP的出现为Kotlin编程带来了更加高效和强大的编译时处理工具,使得开发者能够更轻松地进行元编程、自动生成代码以及其他定制化操作。在接下来的章节中,我们将深入了解KSP的工作原理和使用方法,帮助您更好地掌握这项新技术。

4. 编写第一个KSP处理器

Kotlin Symbol Processor(KSP)为我们提供了在编译时处理Kotlin代码的能力。在本节中,我们将详细介绍编写第一个KSP处理器的步骤,并通过示例代码演示如何创建和注册一个简单的KSP处理器。

步骤1:添加依赖

首先,在项目的build.gradle文件中添加KSP的依赖:

dependencies {implementation "com.google.devtools.ksp:symbol-processing-api:$ksp_version"ksp "com.google.devtools.ksp:symbol-processing:$ksp_version"
}

步骤2:创建KSP处理器

接下来,创建一个Kotlin类,该类将作为我们的KSP处理器。假设我们想要创建一个处理器,用于查找并输出所有带有@CustomAnnotation注解的元素:

import com.google.devtools.ksp.processing.*class CustomAnnotationProcessor : SymbolProcessor {override fun process(resolver: Resolver) {val customAnnotations = resolver.getSymbolsWithAnnotation("com.example.CustomAnnotation")for (annotation in customAnnotations) {println("Found element with @CustomAnnotation: ${annotation.simpleName}")}}
}

步骤3:注册KSP处理器

在项目的src/main/resources/META-INF/services目录下创建一个名为com.google.devtools.ksp.processing.SymbolProcessor的文件,文件内容为我们创建的KSP处理器的全限定类名:

com.example.CustomAnnotationProcessor

步骤4:使用KSP处理器

现在,我们已经创建并注册了我们的KSP处理器。在我们的Kotlin代码中,我们只需添加@CustomAnnotation注解,处理器就会在编译时找到这些注解并执行相应的操作:

@CustomAnnotation
class MyClass {// Class implementation
}

当我们编译项目时,KSP处理器将会被触发,找到带有@CustomAnnotation注解的元素,并输出它们的名称。

通过以上步骤,我们成功地创建了并注册了一个简单的KSP处理器。当然,实际的KSP处理器可能会更加复杂,可以进行更多种类的操作,如生成代码、分析代码结构等。

总之,KSP为我们提供了一种强大的编译时处理工具,可以帮助我们在编译阶段进行更多定制化的操作,从而提高代码质量和开发效率。在接下来的章节中,我们将继续探索更多KSP的特性和应用场景。

5. KSP的核心功能和应用场景

Kotlin Symbol Processor(KSP)作为一种编译时处理工具,具有强大的功能,可以在编译阶段对Kotlin代码进行各种定制化操作。本节将深入探讨KSP的核心功能以及它在不同应用场景中的重要作用。

KSP的核心功能

KSP的核心功能包括符号处理和代码生成。它允许开发者在编译时访问和分析Kotlin代码中的符号(Symbols),如类、函数、属性等。通过符号处理,开发者可以获取代码的结构信息并进行各种操作,如验证、生成新代码等。

另一个重要的功能是代码生成,即在编译时生成新的Kotlin代码。KSP允许开发者根据分析得到的信息生成新的类、函数、属性等,从而实现自动化的代码生成和扩展。

KSP的应用场景

KSP在许多应用场景中能够发挥重要作用,以下是一些常见的应用场景:

  1. 自动代码生成: KSP可以用于自动生成重复性代码,减少手动编写的工作量。例如,可以使用KSP生成类型转换代码、序列化/反序列化代码等。

  2. 依赖注入: KSP可以在编译阶段自动生成依赖注入的代码,提供更快的启动时间和类型安全。与传统的运行时注入框架相比,KSP可以在编译时捕获错误,并提供更好的性能。

  3. 路由和导航: 在Android应用开发中,KSP可以帮助生成路由和导航代码,减少手动维护路由表的工作。

  4. 元编程: KSP可以用于执行元编程任务,如分析注解、生成元数据等。这有助于在编译阶段进行更丰富的元数据处理。

  5. 性能优化: 通过在编译阶段进行一些操作,如生成高效的代码、优化资源访问等,KSP可以提高应用的性能和响应速度。

下面是一个简单示例,演示了如何使用KSP生成一个单例类:

@GenerateSingleton
class MySingleton {// Singleton implementation
}

通过定义@GenerateSingleton注解,并在KSP处理器中捕获带有该注解的类,可以自动生成单例模式的代码。

总之,KSP的核心功能和灵活性使其在许多应用场景中都能发挥重要作用,帮助开发者提高代码质量、减少重复性工作,以及优化应用性能。在实际开发中,我们可以根据具体需求充分利用KSP的能力,提升开发效率和代码可维护性。

6. 深入理解KSP的工作原理

Kotlin Symbol Processor(KSP)作为编译时处理工具,背后有着复杂而精巧的工作原理。本节将深入探讨KSP在编译期的工作流程,以及它是如何解析和处理Kotlin源代码中的符号信息的。

KSP的工作原理和流程

  1. 注解处理器的注册: 在项目中使用KSP时,需要在Kotlin源代码中标记需要处理的元素,例如类、函数、属性等。这些元素会使用注解进行标记,通常会定义一个特定的注解。在KSP中,我们需要注册自定义的处理器,这些处理器会在编译期被触发执行。

  2. 编译器调用KSP处理器: 当Kotlin编译器开始编译项目时,它会扫描项目中的注解,发现使用了KSP注解的元素。然后,编译器会调用已注册的KSP处理器,将相应的符号信息传递给处理器。

  3. 符号信息解析: 在处理器中,KSP会解析传递过来的符号信息,这些信息包括注解所在的类、函数、属性的名称、类型、修饰符等。处理器可以通过这些信息了解代码的结构和特性。

  4. 符号处理和代码生成: 在处理器中,开发者可以根据解析得到的符号信息执行各种操作,如生成新代码、验证代码的正确性、收集元数据等。这些操作可以根据项目的需求进行定制。

  5. 生成代码文件: 处理器可以生成新的Kotlin源代码文件,这些文件会被添加到项目中。编译器会继续处理这些新生成的文件,将它们编译成字节码并包含在最终的应用程序中。

KSP如何解析和处理符号信息

KSP通过编译器提供的API来解析和处理Kotlin源代码中的符号信息。开发者可以使用这些API访问类、函数、属性等元素的信息,如名称、类型、修饰符等。以下是一个简单的示例,演示了如何使用KSP API访问类的信息:

@MyAnnotation
class MyClass {// Class definition
}
class MyProcessor : SymbolProcessor {override fun process(resolver: Resolver) {val annotatedClasses = resolver.getSymbolsWithAnnotation("MyAnnotation")for (symbol in annotatedClasses) {val className = symbol.qualifiedNameval classType = symbol.type// Perform processing on the annotated class}}
}

在上面的示例中,resolver.getSymbolsWithAnnotation("MyAnnotation")会返回所有被@MyAnnotation注解标记的类的符号信息。通过符号的qualifiedNametype属性,我们可以获取类的名称和类型信息,从而进行进一步的处理。

总结起来,KSP的工作原理涉及编译器、注解、处理器之间的协作。KSP通过解析和处理Kotlin源代码中的符号信息,实现了在编译期对代码进行定制化操作的能力。了解KSP的工作原理有助于我们更好地使用这一强大的编译时处理工具,提高代码质量和开发效率。

7. 高级KSP技巧与最佳实践

Kotlin Symbol Processor (KSP)作为编译时处理工具,提供了许多高级技巧和最佳实践,可以帮助开发者更有效地利用其功能。本节将分享一些高级的KSP技巧,并介绍编写高质量KSP处理器的最佳实践。

条件性代码生成

在某些情况下,我们可能希望根据特定的条件生成代码。KSP允许我们通过在处理器中使用Kotlin的语言特性来实现条件性代码生成。以下是一个示例,演示了如何根据注解的参数生成不同的代码:

@ConditionalAnnotation(enabled = true)
class MyClass {// Class definition
}
class MyProcessor : SymbolProcessor {override fun process(resolver: Resolver) {val annotatedClasses = resolver.getSymbolsWithAnnotation("ConditionalAnnotation")for (symbol in annotatedClasses) {val annotation = symbol.getAnnotation<ConditionalAnnotation>()val isEnabled = annotation.enabledif (isEnabled) {// Generate code for enabled case} else {// Generate code for disabled case}}}
}

在上面的示例中,根据注解的参数enabled的值,我们可以生成不同的代码块。这种条件性代码生成可以根据项目需求实现更灵活的处理逻辑。

自定义符号处理

KSP允许开发者自定义符号处理逻辑,以实现更复杂的操作。除了基本的符号信息,我们还可以使用KSP提供的API来访问更多元素,如函数的参数、泛型信息等。以下是一个示例,展示了如何获取函数的参数列表:

class MyProcessor : SymbolProcessor {override fun process(resolver: Resolver) {val functions = resolver.getSymbolsWithAnnotation("MyAnnotation").filterIsInstance<FunctionSymbol>()for (function in functions) {val parameters = function.valueParameters// Process function parameters}}
}

最佳实践

编写高质量的KSP处理器需要遵循一些最佳实践,以确保代码的可维护性和性能。以下是一些推荐的最佳实践:

  1. 错误处理: 在处理器中进行错误处理非常重要。使用resolver.reportError()来报告错误,并提供有用的错误信息,以帮助用户识别和解决问题。

  2. 性能优化: 考虑到KSP处理器在编译期执行,性能是关键。避免不必要的符号解析和处理,以提高处理器的执行速度。

  3. 代码生成风格: 生成的代码应该符合项目的代码风格和规范。可以使用Kotlin的CodeGenerator来生成格式化的代码。

  4. 文档和注释: 对于复杂的处理器逻辑,编写清晰的文档和注释是必要的,以便其他开发者能够理解和维护代码。

  5. 单元测试: 对于处理器的核心逻辑,编写单元测试是一种有效的方式来验证其功能和正确性。

通过使用高级的KSP技巧和遵循最佳实践,开发者可以更好地利用KSP的功能,提高代码质量和开发效率。同时,了解如何优化处理器的性能和可维护性,将有助于确保项目的成功和可持续发展。

8. KSP的未来展望

随着Kotlin Symbol Processor (KSP)的出现和不断发展,它在未来的Kotlin生态中可能会扮演着更为重要的角色。本节将讨论KSP的未来展望,以及它可能对编程社区带来的影响和创新。

KSP的未来发展趋势

KSP作为新一代的符号处理工具,正逐步获得更多的关注和应用。从KSP的设计和功能来看,我们可以预见以下几个方面可能的发展趋势:

  1. 生态整合: 随着KSP的成熟和普及,我们可以期待更多的Kotlin库和框架会开始采用KSP来进行编译期的处理,以提高性能和扩展性。

  2. 功能丰富: KSP在当前已经具备了许多强大的功能,但未来还有可能进一步丰富其功能集,以满足不断变化的编程需求。

  3. 工具支持: 随着KSP的发展,我们可能会看到更多的开发工具和插件开始支持KSP,从而提供更便捷的开发体验。

KSP的影响和创新

KSP作为编译时处理工具,为编程社区带来了一些创新和影响:

  1. 性能提升: KSP相较于传统的KAPT在性能方面有着巨大的优势,可以显著减少编译时间,提高开发效率。

  2. 代码生成: KSP使得代码生成更加灵活和高效。通过在编译期生成代码,可以减少运行时的反射和解析操作,提高应用的性能。

  3. 扩展性: KSP的设计使得其具备更好的扩展性,可以更容易地集成到现有的编译流程中,实现自定义的符号处理逻辑。

  4. 语法支持: 由于KSP在编译时操作Kotlin源代码,它可以更深入地理解和处理Kotlin语法,从而提供更强大的功能。

总体而言,KSP在未来将继续影响着Kotlin编程的发展,并为开发者提供更多的可能性和创新空间。通过使用KSP,我们可以更好地利用编译期的信息来实现各种自动化任务,从而提高代码质量、开发效率和应用性能。

9. 结论

Kotlin Symbol Processor (KSP) 不仅是一项引人注目的技术,还代表着编程领域中的一次重要创新。通过在编译期间处理符号,KSP为开发者提供了更广阔的可能性,能够自动化繁琐的任务、提高代码质量,并在一定程度上改善开发体验。

在本文中,我们深入探讨了KSP的定义、核心功能以及与KAPT的比较。我们了解了如何编写第一个KSP处理器,并介绍了KSP在不同应用场景中的重要作用。我们还深入剖析了KSP的工作原理,以及如何应用高级技巧和最佳实践来编写高质量的KSP处理器。最后,我们展望了KSP在未来的发展趋势,以及它可能对编程社区带来的影响和创新。

10. 参考资料

如果你想深入了解KSP,以下是一些相关的文档、教程和资源,可以帮助你更好地掌握和应用这一技术:

  • 官方KSP文档
  • KSP示例项目
  • KSP的GitHub仓库
  • Kotlin官方文档
  • KAPT与KSP的比较
  • ksp-sample

鼓励每位开发者深入学习和尝试KSP,探索它在Kotlin编程中的应用。通过充分利用KSP的功能,你可以提高自己的开发效率,改善代码质量,甚至创造出一些独特的解决方案。KSP代表了Kotlin生态中的一次重要进步,它将继续为开发者们带来更多的机会和挑战,为编程领域带来新的活力。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

运动耳机推荐,骨传导运动耳机哪款好?

作为一个运动爱好者&#xff0c;一款合适的运动耳机至关重要&#xff0c;因为音乐能有效地激发人体潜能&#xff0c;充分释放能量&#xff0c;达到更好的运动效果&#xff0c;那么面对产品种类众多的运动耳机&#xff0c;该如何选择呢&#xff1f;个人建议的话首选骨传导耳机&a…

redis的基础命令01

1、操作库的指令 1、清除当前库---flushdb 2、清除所有库---flushAll 2、操作key的指令 最常用的指令get、set 1&#xff09;set key value 2&#xff09;get key 基础指令 1、del 删除单个&#xff1a;del key 、批量删除&#xff1a;del key1 key2 key3 2、exists 判断key是否…

B站发布财报,正式会员数达2.14亿

KlipC报道&#xff1a;B站公布了截至2023年6月30日的未经审计的财务报告&#xff0c;据数据显示&#xff0c;B站总营收达同比增长8%达53.04亿元人民币&#xff0c;毛利润同比增长66%&#xff0c;其中广告业务收入同比增长36%达16亿人民币。财报发布后&#xff0c;B站美股盘前一…

QT如何打包

目录 1.windeployqt工具 2.工具位置 3.使用方法 4.注意事项 Qt Creator 默认以动态链接的方式生成可执行文件&#xff0c;该文件无法独立运行&#xff0c;必须为其提供所需的动态链接库。也就是说&#xff0c;只分享 Qt Creator 生成的可执行文件是不行的&#xff0c;必须将…

rabbitmq容器启动后修改连接密码

1、进入容器 docker exec -it rabbitmq bash 2、查看当前用户列表 rabbitmqctl list_users 3、修改密码 rabbitmqctl change_password [username] ‘[NewPassword]’ 4、修改后退出容器 ctrlpq 5、退出容器后即可生效&#xff0c;不需要重启容器

关于内点定义不同的讨论

根据和译者联系后&#xff0c;根据提供P660页的关于内点的定义与其他国内教材不同。 《离散数学及其应用&#xff08;原书第8版&#xff09;》ISBN:978-7-111-63687-8内点定义如下图所示 因此 《离散数学及其应用&#xff08;原书第8版&#xff09;》ISBN:978-7-111-63687-8 第…

Springboot 实践(7)springboot添加html页面,实现数据库数据的访问

前文讲解&#xff0c;项目已经实现了数据库Dao数据接口&#xff0c;并通过spring security数据实现了对系统资源的保护。本文重点讲解Dao数据接口页面的实现&#xff0c;其中涉及页面导航栏、菜单栏及页面信息栏3各部分。 1、创建html页面 前文讲解中&#xff0c;资源目录已经…

华为公布一项倒装芯片封装技术:能大幅改善CPU散热

华为技术有限公司日前公开了一项名为“具有改进的热性能的倒装芯片封装”专利&#xff0c;申请公布号为CN116601748A。 该专利实施例提供了一种倒装芯片封装、一种装备有应用封装结构的电路的装置以及一种组装封装的方法。 更直观来说&#xff0c;就是一种提供芯片与散热器之…

RestTemplate

RestTemplate介绍 RestTemplate是Spring提供的用于访问RESTful服务的客户端&#xff0c;RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。RestTemplate默认依赖JDK提供http连接的能力&#xff08;HttpURLConnection&#xff09;&#xff0c;…

银河麒麟服务器v10 sp1 .Net6.0 上传文件错误

上一篇&#xff1a;银河麒麟服务器v10 sp1 部署.Net6.0 http https_csdn_aspnet的博客-CSDN博客 .NET 6之前&#xff0c;在Linux服务器上安装 libgdiplus 即可解决&#xff0c;libgdiplus是System.Drawing.Common原生端跨平台实现的主要提供者&#xff0c;是开源mono项目。地址…

WPF CommunityToolkit.Mvvm

文章目录 前言ToolkitNuget安装简单使用SetProperty&#xff0c;通知更新RealyCommandCanExecute 新功能&#xff0c;代码生成器ObservablePropertyNotifyCanExecuteChangedForRelayCommand其他功能对应关系 NotifyPropertyChangedFor 前言 CommunityToolkit.Mvvm&#xff08;…

Docker网络与资源控制

一、Docker 网络实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Container-IP&#xff0c;同时Docker网桥是每个容器的默认网关。因为在同一宿…

期待相聚|2023 Google 谷歌开发者大会现场见

直达科技前沿 点亮技术灵感 激发新思妙想 收获多元共进 长按下方图片&#xff0c;扫码报名参会 *仅出于确认身份&#xff0c;请填写与身份证件一致的姓名&#xff0c;并确认邮箱地址及联系电话准确无误。 2023 Google 开发者大会主旨演讲将会分享 Google 如何通过更智能、更…

linux中ubuntu安装hashcat方法以及使用GPU破解

一、linux安装hashcat git clone https://github.com/hashcat/hashcat.git make make install二、安装驱动 驱动版本安装大全&#xff1a;https://developer.nvidia.com/cuda-toolkit-archive 查看自己显卡选择对应的版本&#xff0c;根据下面命令无脑安装就行了 wget https:/…

Python functools module 的介绍与应用

Python functools module 的介绍与应用 functools module lru_cache from functools import lru_cache import timelru_cache(maxsizeNone) # 设置缓存大小为无限制 def my_function(x):for i in range(1000):x xfor j in range(100):x xreturn x# 第一次调用函数&#xff…

投资不识筹码峰,炒遍A股也枉然? | 如何用python计算筹码分布数据

你听说过股市上著名的丁蟹效应吗&#xff1f; 你知道丁蟹报仇点到为止&#xff0c;丁蟹报恩家破人亡吗&#xff1f; 你又是否曾在微信群中见过这些表情包&#xff1f; 01 大时代 不知道大家有没有看过《大时代》这部剧&#xff0c;看过的欢迎点我头像交流讨论。 剧中逆天强运…

【LeetCode】买卖股票的最佳时机最多两次购买机会

买卖股票的最佳时机 题目描述算法分析程序代码 链接: 买卖股票的最佳时机 题目描述 算法分析 程序代码 class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();vector<vector<int>> f(n,vector<int>(3,-0x3f3f3f))…

docker可视化工具Portainer

1:Portainer简介 Portainer是一个docker可视化管理工具&#xff0c;可以非常方便地管理docker镜像容器。官网地址&#xff1a;https://www.portainer.io/ 注&#xff1a;现在Portainer有BE&#xff08;收费&#xff09;和CE&#xff08;免费&#xff09;版本&#xff0c;安装的…

【03 英语语法:从句(名词从句、定语从句/形容词从句、状语从句/副词从句)】

从句 从句&#xff1a;名词从句、定语从句、状语从句&#xff08;名定状名形副&#xff09;1. 名词从句&#xff08;名词&#xff09;&#xff1a;主语、宾语、表语、同位语、宾补▲名词从句的种类&#xff08;按引导词&#xff09;&#xff1a; that、whether、疑问词 句子⑴…

免费内网穿透哪个好?

神卓互联是一种内网穿透技术&#xff0c;可以实现在外部网络访问公司内网的服务。通过建立一个加密的通道&#xff0c;神卓互联可以将内网的动态IP绑定技术&#xff0c;实现远程访问。 使用神卓互联进行内网穿透的步骤如下&#xff1a; 在公司内网中&#xff0c;安装并配置神卓…