我已经阅读了Kotlin文档(https://kotlinlang.org/docs/packages.html),并且我理解在导入包时,包名称不需要与存储包的文件夹的路径相匹配(与Java中的情况不同).

我在创建包并将其导入到其他类中时没有问题.

我想要了解的是,how the compiler can find the file to import?

例如:

如果文件导入animals.mammals.cats.*:

import animals.mammals.cats.*

...

要导入的实体不需要存储在文件/animals/mammals/cats.kt中,只要包名是"Animals.mam-malls.cat":

package animals.mammals.cats

...

例如,该Kotlin文件可以存储在src/animals/kittens中.

换句话说,既然包名没有帮助,import如何定位要加载的文件呢?

谢谢!

推荐答案

首先,请注意,import语句本身并不是最重要的.这只是一种方便的语法,可以避免在整个文件中到处指定包.但从技术上讲,您不需要导入任何内容来使用当前文件外部的声明--您只需使用它们的fully qualified name(也称为FQN),即包名+声明名.

现在,让我们来回答你的问题.当您运行编译器时,您将同时提供要编译的完整文件集的路径:您将编译一个模块,而不是单个文件.因此,它可以访问所有这些文件中的所有声明,并维护自己关于可用类和顶级函数以及所有符号的数据 struct .因此它可以仅使用声明的FQN来存储和查找声明.(DISCLAIMER: I'm no expert and I don't actually know how it's done internally, but I'm just guessing that conceptually it's like storing a big mapping between FQN and the information about the corresponding declaration.)

如果您使用的声明不在正在编译的文件集中,则它必须位于dependencies个文件中的一个文件中.您可以通过指定包含已编译类的JAR列表来告诉编译器可用的依赖项.编译时所有可用类的列表称为compile classpath.这就是为什么用来构建项目的工具(例如Gradle或IDE)需要知道这些依赖关系,以便在为您调用编译器时可以将它们的声明放在compile classpath上.然后,就像正在编译的声明一样,编译器可以很容易地查找来自编译类路径的声明(路径已作为参数提供给编译器).

现在,当您实际run编译的程序时,至少在JVM上,所需的类必须放在runtime classpath上--这是提供给java程序的一组类.在程序运行时查找这些声明是在classloaders完成的.有多个按层次 struct 组织的类加载器,但这里不需要详细说明.基本上,每次在程序运行时第一次使用类时,都会要求一个类加载器将该类加载到内存中.类加载器有不同的实现,但最常见的是URLClassLoader,它被提供了一些包含类的JAR的URL,并且知道如何按需将类从这些JAR读取到内存中.

Kotlin相关问答推荐

如何在Jetpack Compose中从领域查询中读取数据?

如何让Gradle8+在编译Kotlin代码之前编译Groovy代码?然后把它们混合在一个项目中?

某些公共函数显然不能在类实例上访问;Klaxon示例

Kotlin多平台(KMP)保存到文件不能在iOS上保存

新的jOOQ Gradle插件无法正确处理自引用关系

kotlin 模式匹配如何像 scala 一样工作

在jetpack compose中将默认方向设置为横向?

有没有一种简单的方法可以将数组/列表中的每个元素相互相乘 - Kotlin?

如何在 Compose 中创建可重用的修饰符?

为什么 Kotlin 扩展运算符在传递原始可变参数时需要 toTypedArray()?

禁用 Android 12 默认启动画面

Kotlin 静态函数:伴生对象,@JvmStatic @JvmField

是否可以在 kotlin 中嵌套数据类?

Kotlin - mutableMapOf() 会保留我输入的顺序

Kotlin 类的调用方法

Kotlin reflect proguard SmallSortedMap

android Room 将 Null 作为非 Null 类型返回

通过在 kotlin-gradle 中使用子项目Unresolved reference: implementation

uses-sdk:minSdkVersion 16 不能小于库中声明的版本 23

如何判断数据是否插入到房间数据库中