11-包声明与使用
4.4 包声明与使用
为了更好地组织和管理Java类,Java提供了包管理机制,用于区别类名的命名空间并进行访问控制。和Java一样,Kotlin也存在包的概念,主要用来区分同名源代码文件和组织项目结构。不过,由于允许包级函数和包级属性的存在,因此Kotlin包的内容更加丰富,不像Java包只包含类和接口。
与Java源文件相同,Kotlin源文件最多包含一个package语句,而且必须放在第一行(除注解外)。除此之外,源文件中的所有内容(无论是类还是函数)都应该包含在声明的包内。
package foo.bar
fun baz() {}
class Goo {}
// ……
上面的示例中,Goo类的全名是foo.bar.Goo,baz()的全名是foo.bar.baz。如果没有指定包,则该文件的内容属于无名字的默认包。
Kotlin允许在package语句前添加注解,这些注解不针对package语句,而是针对整个Kotlin源文件,需要在注解前加上@file:标识符,主要有两种方式的注解。
@kotlin.jvm.JvmName(val name: String)
这种注解可以用来修饰文件和函数,用于指定目标元素编译后的名称。例如,使用该注解指定以Kt结尾的“文件类”的名称。
@kotlin.jvm.JvmMultiFileClass
这种注解只能修饰文件,告诉编译器:文件里定义的包级函数和包级属性只是class文件的一部分,还有一部分定义在其他文件里。该注释一般需要与上面的JvmName注解配合使用。
@file:kotlin.jvm.JvmMultifileClass
@file:kotlin.jvm.JvmName("StandardKt")
package kotlin
inline fun <R> synchronized(lock: Any, block: () -> R): R {
/*…*/
}
Synchronized.kt文件用两个注解表示,除了synchronized()函数被包含在 StandardKt.class文件里以外,这个class的另一部分内容被包含在Standard.kt 文件里。
前面说过,Kotlin包内的元素比Java包更为丰富,除了包含类和接口外,还包含函数和属性。因此,Kotlin的import语句除了可以导入类和接口外,还可以导入包级函数和包级属性。
Kotlin不允许导入的元素重名,一旦出现重名,就需要使用as自定义导入名称。而在Java的包规则中,导入重名的元素是被允许的,只要位于不同的包即可。
//Java导入重名被允许
import foo.a.Bar
import foo.b.Bar
//Kotlin导入重名不被允许
import foo.a.Bar
import foo.b.Bar as BBar
在Kotlin中,使用【import包名.函数名/属性名】的形式来导入包级函数和包级属性,并不需要写出文件名。例如存在一个名为Test.kt的文件。
// test.Test.kt
fun sayHello() = println("Hello")
val a = 10
//Kotlin导入函数和属性
import test.Test.sayHello
import test.Test.a
Java文件的导入方式如下。
import test.TestKt;
TestKt.sayHello();
System.out.println(TestKt.a)
或者使用“import static”静态方式导入。
import static test.TestKt.sayHello;
import static test.TestKy.a;
sayHello();
System.out.println(a);
需要注意的是,Kotlin并没有像Java一样提供“import static”静态方式导入。导入一个Java类的静态方法可以用【import Java 类.静态方法】的形式;如果需要导入一个Kotlin类的静态方法,则可以用【import Kotlin类.Companion.静态方法】的形式。例如Test.kt文件和Test.java文件。
Test.kt文件如下。
package test
class TestKotlin {
companion object {
fun printWorld() = println("World")
}
}
Test.java文件如下。
package test;
public class TestJava {
public static void printHello() {
System.out.println("Hello");
}
}
如果需要导入上面文件的静态方法,可以参考下面的实例。
import test.TestKotlin.Companion.printWorld
import test.TestJava.printHello
fun main(vararg args: String) {
printHello() //输出Hello
printWorld() //输出 World
}
细心的读者会发现,在Kotlin中使用某些API时,是不需要使用import导入任何资源的,这是因为Kotlin会默认导入一些包,这些包包括以下形式。
- kotlin.*。
- kotlin.annotation.*。
- kotlin.collections.*。
- kotlin.comparisons.*。
- kotlin.io.*。
- kotlin.ranges.*。
- kotlin.sequences.*。
- kotlin.text.*。
除了上面的原生API以外,根据目标平台还会导入额外的包。
JVM平台默认导入的包有以下几种。
- java.lang.*。
- kotlin.jvm.*。
JavaScript平台默认导入的包有kotlin.js.*。