阅读更多

1顶
0踩

移动开发

转载新闻 Kotlin 1.2 的新增特性

2017-12-05 10:59 by 副主编 jihong10102006 评论(1) 有10902人浏览
引用


目录

多平台项目 (实验性)

多平台项目是 Kotlin 1.2 中的一个新的实验性功能,允许你在 Kotlin – JVM, JavaScript 和(将来的)Native 上所支持的目标平台之间重用代码。在多平台项目中,你有三种模块:
  • 一个通用(common)的模块 —— 包含非特定于任何平台的代码,以及不附带依赖于平台的 API 实现的声明。
  • 平台(platform)模块 —— 包含用于特定平台的通用模块中与平台相关声明的实现,以及其他平台相关代码。
  • 常规(regular)模块针对特定的平台,可以是平台模块的依赖,也可以是依赖的平台模块。
在为特定平台编译多平台项目时,会生成通用及特定平台相关部分的代码。

多平台项目支持的一个关键特性是可以通过 expected 以及 actual 声明来表达通用代码对平台特定部分的依赖关系。expected 声明指定了一个 API(类、接口、注释、顶层声明等)。actual 声明或是 API 的平台相关实现,或是在外部库中 API 现有实现的别名引用。下面是一个示例:

在通用代码中:
// expected platform-specific API:
expect fun hello(world: String): String

fun greet() {
    // usage of the expected API:
    val greeting = hello("multi-platform world")
    println(greeting)
}

expect class URL(spec: String) {
    open fun getHost(): String
    open fun getPath(): String
}

在 JVM 平台中,代码如下所示:
actual fun hello(world: String): String =
    "Hello, $world, on the JVM platform!"

// using existing platform-specific implementation:
actual typealias URL = java.net.URL

详细信息请参考此文档,并按照步骤构建多平台项目。

其他语言特性

注解中的数组常量

从 Kotlin 1.2 开始,注解的数组参数可以使用新的数组常量语法而不是 arrayOf 函数来传递:
@CacheConfig(cacheNames = ["books", "default"])
public class BookRepositoryImpl {
    // ...
}

数组常量语法被限制为注释参数。

Lateinit 顶级属性和局部变量

lateinit 修饰符现在可以用在顶级属性和局部变量上。例如,当一个 lambda 作为构造函数参数传递给一个对象时,后者可以用于引用另一个必须稍后定义的对象:

lateinit修饰符现在可以用在顶级属性和局部变量上。 例如,当作为构造函数参数传递给一个对象的 lambda 引用另一个对象时,稍后必须定义的对象可以使用:
class Node<T>(val value: T, val next: () -> Node<T>)

fun main(args: Array<String>) {
    // A cycle of three nodes:
    lateinit var third: Node<Int>
    
    val second = Node(2, next = { third })
    val first = Node(1, next = { second })
    
    third = Node(3, next = { first })
    
    val nodes = generateSequence(first) { it.next() }
    println("Values in the cycle: ${nodes.take(7).joinToString { it.value.toString() }}, ...")
}

循环中的值:1, 2, 3, 1, 2, 3, 1, ...

目标平台:运行 Kotlin 1.2.0 版本的 JVM

检查一个 lateinit 变量是否被初始化

现在可以在属性引用上使用 isInitialized 来检查 lateinit 变量是否已经被初始化:
class Foo {
    lateinit var lateinitVar: String
    
    fun initializationLogic() {
        println("isInitialized before assignment: " + this::lateinitVar.isInitialized)
        lateinitVar = "value"
        println("isInitialized after assignment: " + this::lateinitVar.isInitialized)    
    }
}
fun main(args: Array<String>) {
    Foo().initializationLogic()
}


isInitialized before assignment: false
isInitialized after assignment: true

目标平台:运行 Kotlin 1.2.0 版本的 JVM

带默认函数参数的内联函数

内联函数现在允许其内联函数参数具有默认值:

inline fun <E> Iterable<E>.strings(transform: (E) -> String = { it.toString() }) = 
map { transform(it) }

val defaultStrings = listOf(1, 2, 3).strings()
val customStrings = listOf(1, 2, 3).strings { "($it)" } 

fun main(args: Array<String>) {
    println("defaultStrings = $defaultStrings")
    println("customStrings = $customStrings")
}

defaultStrings = [1, 2, 3]
customStrings = [(1), (2), (3)]

目标平台:运行 Kotlin 1.2.0 版本的 JVM

来自显式类型的信息被用于类型推断

Kotlin 编译器现在可以使用类型转换信息进行类型推断。如果调用一个返回类型参数 T 并将返回值转换为特定类型 Foo 的泛型方法,则编译器现在可以理解此调用的 T 需要绑定到 Foo 类型。

这对 Android 开发者来说尤其重要,因为编译器现在可以在 Android API level 26 中正确分析范型 findViewById 调用:

val button = findViewById(R.id.button) as Button


改进 smart cast

当一个变量从一个安全调用表达式中被赋值并且被检查为 null 时,smart cast 也被应用到安全调用接收器中:
un countFirst(s: Any): Int {
    val firstChar = (s as? CharSequence)?.firstOrNull()
    if (firstChar != null)
    return s.count { it == firstChar } // s: Any is smart cast to CharSequence
    
    val firstItem = (s as? Iterable<*>)?.firstOrNull()
    if (firstItem != null)
    return s.count { it == firstItem } // s: Any is smart cast to Iterable<*>
    
    return -1
}
fun main(args: Array<String>) {
    val string = "abacaba"
    val countInString = countFirst(string)
    println("called on \"$string\": $countInString")
    
    val list = listOf(1, 2, 3, 1, 2)
    val countInList = countFirst(list)
    println("called on $list: $countInList")
}

called on "abacaba": 4
called on [1, 2, 3, 1, 2]: 2

目标平台:运行 Kotlin 1.2.0 版本的 JVM

而且,现在允许在 lambda 中进行智能的强制转换,这些局部变量只在 lambda 之前被修改:
fun main(args: Array<String>) {
    val flag = args.size == 0
    
    var x: String? = null
    if (flag) x = "Yahoo!"
    
    run {
        if (x != null) {
            println(x.length) // x is smart cast to String
        }
    }
}


目标平台:运行 Kotlin 1.2.0 版本的 JVM

支持 ::foo 作为 this::foo 的缩写

现在可以使用 ::foo 替代 this::foo,写入一个绑定的可调用的引用,而不用明确的接收器。这也使得可调用的引用在你引用外部接收者的成员的 lambda 中更方便使用。

破坏性变更:try 块后面的 sound smart casts

早些时候,Kotlin 使用了 try 块中的赋值,以在块之后进行 smart casts,这可能会破坏类型及 null 值的安全性并导致运行时失败。这个版本修复了此问题,使 smart casts 更严格,但破坏了一些依赖这种 smart casts 的代码。

要切换到旧的 smart casts 行为,传递 fallback 标志 -Xlegacy-smart-cast-after-try 作为编译器参数。它将在 Kotlin 1.3 中被弃用。

弃用:数据类的覆写性拷贝

当从已经具有相同签名的拷贝函数的类型派生数据类时,为数据类生成的 copy 实现使用父类型的默认函数,会导致出现与预期相反的行为,如果父类型没有默认参数,则在运行时失败

导致复制冲突的继承已经被 Kotlin 1.2 中的警告所取代,并且在 Kotlin 1.3 中这将会提示是错误的。

弃用:枚举项中的嵌套类型

在枚举项中,由于初始化逻辑中的问题,定义一个不是内部类的嵌套类型的功能已经被弃用。在 Kotlin 1.2 中这将会引起警告,并将在 Kotlin 1.3 中报错。

弃用:vararg 中的单命名参数

为了与注解中的数组常量保持一致,在命名的表单(foo(items = i)) 中为 vararg 参数传递的单项目已被弃用。请使用具有相应数组工厂函数的展开运算符:
foo(items = *intArrayOf(1))

在这种情况下,有一种优化可以消除冗余数组的创建,从而防止性能下降。单一参数的表单在 Kotlin 1.2 中会引起警告,并将在 Kotlin 1.3 中被移除。

弃用:扩展 Throwable 的泛型类的内部类

继承自 Throwable 的泛型的内部类可能会违反 throw-catch 场景中的类型安全性,因此已被弃用,在 Kotlin 1.2 中会被警告,在 Kotlin 1.3 中将会报错。

弃用:改变只读属性的 backing 字段

在自定义 getter 中通过赋值 field = ... 来改变只读属性的 backing 字段已被弃用,在 Kotlin 1.2 中会被警告,在 Kotlin 1.3 中将会报错。

标准库

Kotlin 标准库 artifacts 及拆分包

Kotlin 标准库现在完全兼容 Java 9 的模块系统,它会禁止对包进行拆分(多个 jar 包文件在同一个包中声明类)。为了支持这一点,引入了新的 artifacts kotlin-stdlib-jdk7 和 kotlin-stdlib-jdk8,取代了旧的 kotlin-stdlib-jre7 和 kotlin-stdlib-jre8。

新 artifacts 中的声明从 Kotlin 的角度来看在相同的包名下可见的,但是对 Java 而言它们有不同的包名。因此,切换到新的 artifacts 不需要对源代码进行任何更改。

确保与新模块系统兼容的另一个更改是从 kotlin-reflect 库中移除 kotlin.reflect 包中的弃用声明。如果使用它们,则需要使用 kotlin.reflect.full 包中的声明,自 Kotlin 1.1 以来该包是被支持的。

windowed, chunked, zipWithNext

Iterable<T>, Sequence<T> 和 CharSequence 的新扩展包含了诸如缓冲或批处理(chunked),滑动窗口和计算滑动平均值 (windowed)以及处理 subsequent item 对 (zipWithNext) 等用例:
fun main(args: Array<String>) {
    val items = (1..9).map { it * it }
    
    val chunkedIntoLists = items.chunked(4)
    val points3d = items.chunked(3) { (x, y, z) -> Triple(x, y, z) }
    val windowed = items.windowed(4)
    val slidingAverage = items.windowed(4) { it.average() }
    val pairwiseDifferences = items.zipWithNext { a, b -> b - a }
    
    println("items: $items\n")
    
    println("chunked into lists: $chunkedIntoLists")
    println("3D points: $points3d")
    println("windowed by 4: $windowed")
    println("sliding average by 4: $slidingAverage")
    println("pairwise differences: $pairwiseDifferences")
}

输出结果:

items: [1, 4, 9, 16, 25, 36, 49, 64, 81]

chunked into lists: [[1, 4, 9, 16], [25, 36, 49, 64], [81]]
3D points: [(1, 4, 9), (16, 25, 36), (49, 64, 81)]
windowed by 4: [[1, 4, 9, 16], [4, 9, 16, 25], [9, 16, 25, 36], [16, 25, 36, 49], [25, 36, 49, 64], [36, 49, 64, 81]]
sliding average by 4: [7.5, 13.5, 21.5, 31.5, 43.5, 57.5]
pairwise differences: [3, 5, 7, 9, 11, 13, 15, 17]

目标平台:运行 Kotlin 1.2.0 版本的 JVM

fill, replaceAll, shuffle/shuffled

添加了一系列扩展函数用于处理列表:针对 MutableList 的 fill, replaceAll 和 shuffle ,以及针对只读 List 的 shuffled:
fun main(args: Array<String>) {
    val items = (1..5).toMutableList()
    
    items.shuffle()
    println("Shuffled items: $items")
    
    items.replaceAll { it * 2 }
    println("Items doubled: $items")
    
    items.fill(5)
    println("Items filled with 5: $items")
}

Shuffled items: [5, 3, 1, 2, 4]
Items doubled: [10, 6, 2, 4, 8]
Items filled with 5: [5, 5, 5, 5, 5]

目标平台:运行 Kotlin 1.2.0 版本的 JVM

kotlin-stdlib 中的数学运算

为满足用户长期以来的需求,Kotlin 1.2 中增加了用于数学运算的 kotlin.math API,也是 JVM 和 JS 的通用 API,包含以下内容:
  • 常量:PI 和 E
  • 三角函数:cos, sin, tan 及其逆函数 acos, asin, atan, atan2
  • 双曲三角函数:cosh, sinh, tanh 及其逆函数 acosh, asinh, atanh
  • 指数函数:pow (扩展函数), sqrt, hypot, exp, expm1
  • 对数函数:log, log2, log10, ln, ln1p
  • Round 函数:
  • ceil, floor, truncate, round (半值取偶)函数
    roundToInt, roundToLong (半值取整)扩展函数
  • 符号函数和绝对值:
  • abs 和 sign 函数
    absoluteValue 和 sign 扩展属性
    withSign 扩展函数
  • 两个数值的 max 和 min
  • 二分表示:
  • ulp 扩展属性
    nextUp, nextDown, nextTowards 扩展函数
    toBits, toRawBits, Double.fromBits (这些都位于 kotlin 包中)

同系列(但不包括常量)的函数也针对 Float 型参数提供了。

BigInteger 和 BigDecimal 的运算与转换

Kotlin 1.2 引入了一组用于操作 BigInteger 和 BigDecimal 以及使用从其他数字类型进行转换的函数。这些函数是:
  • 用于 Int 和 Long 类型的 toBigInteger
  • 用于 Int, Long, Float, Double, 和 BigInteger 类型的 toBigDecimal
  • 算术和位运算符函数:
  • 二元运算符 +, -, *, /, % 和中缀函数 and, or, xor, shl, shr
    一元运算符 -, ++, -- 和一个函数 inv

浮点数转换

添加了新的函数,用于将 Double 和 Float 转换成位表示形式:
  • toBits 和 toRawBits 对于 Double 类型返回 Long,而对于 Float 返回 Int
  • Double.fromBits 和 Float.fromBits 用于从位表示形式中转换为浮点数
Regex 类现在是可序列化的

kotlin.text.Regex 类已成为可序列化的类,现在可以在可序列化的层次结构中使用。

如果满足条件,Closeable.use 可以调用 Throwable.addSuppressed

在一些其他异常处理后,关闭资源期间抛出异常时,Closeable.use 函数可调用 Throwable.addSuppressed。

要启用这个行为,你需要在你的依赖关系中包含 kotlin-stdlib-jdk7。

JVM后端

构造函数调用标准化

自 1.0 以来,Kotlin 开始支持复杂控制流的表达式,例如 try-catch 表达式和内联函数调用。根据 Java 虚拟机规范这样的代码是合法的。不幸的是,当构造函数调用的参数中存在这样的表达式时,一些字节码处理工具不能很好地处理这些代码。

为了减少使用此类字节码处理工具的用户的这个问题,我们添加了一个命令行选项 (-Xnormalize-constructor-calls=MODE),它会告诉编译器为这样的结构生成更多的类 Java 字节码。这里 MODE 的值是以下之一:
  • disable (默认值)—— 以和 Kotlin 1.0 和 1.1 相同的方式生成字节码
  • enable —— 为构造函数调用生成类 Java 字节码。这可以改变类加载和初始化的顺序
  • preserve-class-initialization —— 为构造函数调用生成类 Java 字节码,以确保保持类初始化顺序。这可能会影响应用程序的整体性能;仅在多个类之间共享一些复杂的状态并在类初始化时更新时才使用它。
“手工”的解决方法是将控制流的子表达式的值存储在变量中,而不是直接在调用参数中对它们进行求值。它类似于 -Xnormalize-constructor-calls=enable。

Java 默认方法调用

在 Kotlin 1.2 之前,接口成员在使用 JVM 1.6 的情况下重写 Java 默认方法会在父调用中产生警告:Super calls to Java default methods are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'。在 Kotlin 1.2 中,这将会报错,因此需要使用 JVM 1.8 来编译这些代码。

破坏性变更:平台类型的 x.equals(null) 一致行为

在映射到 Java 原语 (Int!, Boolean!, Short!, Long!, Float!, Double!, Char!) 的平台类型上调用 x.equals(null) 时,如果 x 为 null,则会不正确地返回 true。从 Kotlin 1.2 开始,在平台类型的空值上调用 x.equals(...) 会抛出 NPE(但 x == ... 时并不会)。

要返回到 1.2 之前的行为,请将 -Xno-exception-on-explicit-equals-for-boxed-null 标志传递给编译器。

破坏性变更:通过内联的扩展接收器修复平台的 null 转义

在平台类型空值上调用的内联扩展函数并没有检查接收器是否为 null,并因此允许 null 转义到其他代码中。Kotlin 1.2 在调用点强制执行此检查,如果接收方为空,则抛出异常。

要切换到旧行为,请将 fallback 标志 -Xno-receiver-assertions 传递给编译器。

JavaScript 后端

默认启用对类型化数组(TypedArrays)的支持

JS typed arrays 支持将 Kotlin 基本数组(如 IntArray, DoubleArray)转换为 JavaScript 的类型数组,以前这是可选功能,现在默认情况下已启用。

工具

将警告视为错误

编译器现在提供了将所有警告视为错误的选项。在命令行中使用 -Werror,或使用以下的 Gradle 代码:
compileKotlin {
    kotlinOptions.allWarningsAsErrors = true
}
来自: 开源中国
1
0
评论 共 1 条 请登录后发表评论
1 楼 cjz010 2017-12-06 10:28
到底kotlin好在哪?

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • Kotlin 1.2引入多平台项目特性

    最新版本的Kotlin通过多平台项目支持JVM和JavaScript平台的代码共享。除此之外,它还带来了语言和类库方面的大量改进,以及更好的编译器性能。\\Kotlin在1.1版本中就已引入了对JavaScript的支持,而最新版本的Kotlin...

  • 毕业设计&课设_CUMT 信息安全专业毕业设计:基于区块链的能源交易系统,含架构、部署等多方面详细介绍.zip

    毕业设计&课设_CUMT 信息安全专业毕业设计:基于区块链的能源交易系统,含架构、部署等多方面详细介绍.zip

  • 用Python分析文本数据项目

    用Python分析文本数据项目

  • 基于SpringBoot的养老院管理系统源码数据库文档.zip

    基于SpringBoot的养老院管理系统源码数据库文档.zip

  • AshampooUnInstaller v15.00.22 Portable一款强大的卸载工具,彻底、智能著称阿香婆强制卸载软件.rar

    阿香婆软件强制卸载软件 Ashampoo UnInstaller 是一款强大的卸载工具,彻底、智能著称,如果您选择使用Ashampoo安装程序,它会自动分析软件从开始安装到结束的全过程,并为该软件建立一个日志,以便以后更彻底的卸载它,Ashampoo UnInstaller 全面提速!程序采用了新的技术,速度得到了全面提高。Windows 默认应用现在也可以像其它无用程序和恶意软件一样被无忧卸载。摆脱工具栏、插件和其它隐藏的追踪软件,享受安全快捷的上网体验!新的快照比较功能,可以非常简单的创建安装日志,这是旧版本 UnInstaller 粉丝最急需的!新的界面,便捷的批量卸载,以及内置的在线搜索,Ashampoo UnInstaller 一定会让你惊叹无比。快来体验更清晰、更详尽、更快速的 Ashampoo UnInstaller !Ashampoo UnInstallerAshampoo UnInstaller彻底删除无用程序的所有痕迹! 让安装、试用、卸载程序更加轻松。只需点几下,无用的软件、浏览器扩展和工具栏就能从你的硬盘中

  • 基于java的公交车信息管理系统开题报告.docx

    基于java的公交车信息管理系统开题报告

  • 基于java的网络书店系统的开题报告.docx

    基于java的网络书店系统的开题报告

  • forge-1.20.1-47.3.0-installer.jar

    forge-1.20.1-47.3.0-installer

  • 实例-文本进度条源代码

    python

  • 基于springboot云平台的信息安全攻防实训平台源码数据库文档.zip

    基于springboot云平台的信息安全攻防实训平台源码数据库文档.zip

  • 基于SpringBoot的房屋租赁系统源码数据库文档.zip

    基于SpringBoot的房屋租赁系统源码数据库文档.zip

  • 毕业设计&课设_家居物联网毕业设计项目:利用多种设备实现,含架构、目标.zip

    毕业设计&课设_家居物联网毕业设计项目:利用多种设备实现,含架构、目标.zip

  • 基于springboot的非学勿扰学习交流平台源码数据库文档.zip

    基于springboot的非学勿扰学习交流平台源码数据库文档.zip

  • 网络安全教程:基础知识到高级概念全面解读

    内容概要:本文详细介绍了网络安全领域的基础知识和高级概念,涵盖了网络安全概述、网络架构与协议、操作系统安全、网络攻击与防御、密码学与安全协议、身份认证与访问控制、系统漏洞与补丁管理、网络安全实践及发展趋势与挑战等内容。 适合人群:信息安全专业人员、IT运维人员、网络安全工程师、系统管理员。 使用场景及目标:本文不仅帮助读者理解网络安全的理论知识,还能指导实际操作,适用于日常网络安全管理和应急响应。目标在于增强个人和企业对网络安全的认识,提升防护能力。 其他说明:网络安全是一个不断发展变化的领域,文中提到的内容和技术应及时跟进最新的发展动态,确保网络安全的有效性。

  • java毕设项目之基于SpringBoot的特殊儿童家长教育能力提升平台(源码+说明文档+mysql).zip

    环境说明:开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat 开发软件:eclipse/myeclipse/idea Maven包:Maven 浏览器:谷歌浏览器。 项目经过测试均可完美运行

  • 精选微信小程序源码:仿京东白条小程序(含源码+源码导入视频教程&文档教程,亲测可用)

    微信小程序是一种轻量级的应用开发平台,主要针对移动端,由腾讯公司推出,旨在提供便捷的、无需下载安装即可使用的应用服务。"京东白条"是京东金融推出的一种信用消费产品,用户可以在京东商城购物时享受先消费后付款的便利。这款"微信小程序京东白条小程序源码"包含了实现这一功能的小程序源代码,以及相应的导入教程,对于开发者来说,是一个有价值的参考资料。 源码是程序开发的基础,它包含了开发者编写的控制程序行为的指令。在这个案例中,源码可能包括了与京东白条接口交互的逻辑,用户界面设计,以及数据处理等功能。通过分析这些源码,开发者可以学习如何集成京东的API,实现白条的查询、支付和管理等操作。 "源码导入视频教程"和"源码导入文档教程"是辅助开发者理解和使用源码的重要资料。视频教程通常以直观的方式展示源码的导入步骤和环境配置,帮助开发者快速上手。文档教程则可能包含了详细的步骤说明,解决常见问题的技巧,以及开发过程中的注意事项,对于初学者来说尤其有价值。 微信小程序的开发涉及到以下几个关键技术点: 1. **WXML(Weixin Markup Language)**:这是微信小程序的视图层语言,

  • 数字孪生赋能智慧城市大脑建设方案PPT(65页).pptx

    市大脑的基础平台是支撑其高效运行的关键。该平台通过整合电子政务网、视联网、互联网等多网资源,以及云计算、大数据、人工智能等先进技术,打造了一个统一、开放、可扩展的底层架构。在这个基础上,城市大脑能够接入海量数据,包括但不限于视频监控、交通流量、环境监测、民生服务等领域的实时数据,并进行高效处理和分析。这些数据经过清洗、转换、开发后,形成了丰富的数据资源池,为城市治理提供了坚实的数据支撑。 在数据资源的基础上,智慧城市大脑进一步构建了算法服务平台和融合业务应用系统。算法服务平台集成了多种先进的视频分析算法和人工智能算法,如人脸识别、车辆识别、城市问题智能识别等,这些算法能够实时分析视频流和数据流,快速识别城市运行中的问题和异常。同时,融合业务应用系统则将这些算法与城市治理的各个领域相结合,如交通、环保、旅游、医疗等,形成了多个具有实战价值的应用场景。例如,在交通领域,城市大脑能够通过实时分析交通流量和路况信息,优化信号灯控制策略,缓解交通拥堵;在环保领域,则能够实时监测空气质量和水质情况,及时预警环境污染事件。 数字驾驶舱是智慧城市大脑的又一亮点。它作为城市治理能力现代化的新抓手,实现了数据一屏展示、指标一屏分析、指挥一屏联动、场景一屏闭环和治理一屏透视。通过数字驾驶舱,决策者可以直观地看到城市运行的全貌,及时获取关键信息,做出准确的判断和决策。同时,数字驾驶舱还能够根据用户的需求进行个性化配置,提供多种数据处理和分析工具,帮助用户深入挖掘数据价值,提升城市治理的精细化和智能化水平。 智慧城市大脑的建设成效显著。它不仅提高了城市治理的效率和准确性,还带来了显著的社会效益和经济效益。通过优化资源配置、降低运营成本、提升服务质量等方式,智慧城市大脑为城市居民提供了更加便捷、高效、舒适的生活环境。同时,它也为城市的可持续发展注入了新的动力,推动了产业升级和经济转型。可以说,智慧城市大脑已经成为了未来城市发展的重要方向和趋势,它将引领我们走向一个更加智慧、绿色、宜居的城市新时代。 总的来说,智慧城市大脑是一个集数据、算法、应用为一体的综合性解决方案,它通过高度集成和智能分析,实现了城市治理的精细化和智能化。在未来的发展中,随着技术的不断进步和应用场景的不断拓展,智慧城市大脑将会发挥出更加巨大的潜力和价值,为城市的可持续发展和社会的全面进步做出更大的贡献。

  • 毕业设计&课设_景区购票系统(含更新情况、数据字典及多种语言实现).zip

    毕业设计&课设_景区购票系统(含更新情况、数据字典及多种语言实现).zip

Global site tag (gtag.js) - Google Analytics