总结:Kotin这门语言是谁设计的,语法很辣鸡,纯属是为了造门语言而造语言。
文章目录
1.函数式编程
Kotlin 是一种现代的多范式编程语言,支持面向对象编程(OOP)和函数式编程(FP)。函数式编程是一种编程范式,它强调使用纯函数、不可变数据和高阶函数来构建程序。Kotlin 提供了许多特性来支持函数式编程风格,这些特性使得代码更加简洁、易读和易于测试。
2.变换函数map
map
变换函数会遍历接受者集合,让变换器函数作用于集合里的各个元素,返回结果是包含已修改元素的集合,会作为链上下一个函数的输入。
map变换函数和定义的变换器函数做完事情后,返回的是一个新集合,原始集合没有被修改。
fun main() {
val animals = listOf("zebra", "giraffe", "elephant", "rat")
val babies = animals.map { animal -> "A baby $animal is so cute" }
println(babies)
// [A baby zebra is so cute, A baby giraffe is so cute, A baby elephant is so cute, A baby rat is so cute]
}
可以将多个 map 操作链接在一起,以实现更复杂的转换。
val numbers = listOf(1, 2, 3, 4, 5)
val result = numbers.map { it * it } // 计算平方
.map { "Square of $it" } // 转换为描述性字符串
println(result) // 输出: [Square of 1, Square of 4, Square of 9, Square of 16, Square of 25]
3.flatMap
flatMap
函数操作一个集合的集合,将其中多个集合中的元素合并后返回一个包含所有元素的单一集合。
val result = listOf(listOf(1, 2, 3), listOf(4, 5, 6), listOf(7, 8, 9))
val flatMap = result.flatMap { it }
println(flatMap)
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
4.过滤函数filter
filter
函数是一个非常有用的高阶函数,用于从集合中筛选出满足特定条件的元素。它返回一个新的集合,其中只包含那些通过给定谓词(predicate)测试的元素。filter 函数是函数式编程中的一个基本工具,可以帮助你以一种简洁和声明式的方式处理数据。
fun main() {
val list = listOf(1,2,3,4,5,6,7,8,9,10)
val result = list.filter { it % 2 == 0 }
println(result) // [2, 4, 6, 8, 10]
}
fun isEven(number: Int): Boolean {
return number % 2 == 0
}
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evenNumbers = numbers.filter(::isEven)
println(evenNumbers) // 输出: [2, 4, 6]
5.合并函数zip
zip
函数用于将两个集合(如列表)中的元素配对,生成一个新的列表。每个新列表的元素是一个包含两个原集合对应位置元素的 Pair。如果两个集合的长度不同,那么结果列表的长度将与较短的那个集合相同。
fun main() {
val numbers1 = listOf(1, 2, 3)
val numbers2 = listOf(4, 5, 6)
val zipped1 = numbers1.zip(numbers2)
println(zipped1) // 输出: [(1, 4), (2, 5), (3, 6)]
val names = listOf("Alice", "Bob", "Charlie")
val ages = listOf(30, 25, 35)
val zipped2 = names.zip(ages)
println(zipped2) // 输出: [(Alice, 30), (Bob, 25), (Charlie, 35)]
}
6.合并函数fold
fold
函数是一个非常强大的高阶函数,用于对集合中的元素进行累积操作。它从一个初始值开始,依次应用一个函数到每个元素上,并将结果累积起来。fold 是一种减少(reduce)操作,常用于计算总和、乘积、最大值、最小值等。
fun main() {
val numbers1 = listOf(1, 2, 3, 4, 5)
val sum1 = numbers1.fold(0) { acc, i -> acc + i }
println(sum1) // 输出: 15
val numbers2 = listOf(1, 2, 3, 4, 5)
val product = numbers2.fold(1) { acc, i -> acc * i }
println(product) // 输出: 120
}
7.序列
在Kotlin中,序列(Sequence)是一个强大的工具,用于处理大数据集或进行复杂的数据转换。
定义:序列是Kotlin标准库中的一个接口,表示一个元素序列。与普通的集合不同,序列的操作是惰性的,即元素不会在创建序列时立即被处理,而是会在序列被遍历或消费时才按需生成。这种延迟执行的方式允许我们编写出更高效的数据处理逻辑。
序列的操作:
- 中间操作:序列支持多种中间操作,如过滤(filter)、映射(map)、扁平化(flatMap)等。这些操作都是惰性的,只有在序列被消费(如通过toList()、forEach等方法)时,这些操作才会被执行。
- 末端操作:序列的末端操作会执行原来中间操作的所有延迟计算,并返回一个结果,如集合、数字或其他对象。
// 扩展函数 Int.isPrime(),用于判断一个整数是否是质数
fun Int.isPrime(): Boolean {
// 遍历从 2 到当前整数减 1 的所有整数
(2 until this).forEach {
// 如果当前整数能被任何一个遍历到的整数整除,则返回 false,表示不是质数
if (this % it == 0) {
return false
}
}
// 如果没有找到任何能整除当前整数的数,则返回 true,表示是质数
return true
}
fun main() {
// 1-5000之内 可以找到1000个素数
val toList = (1..5000).toList().filter { it.isPrime() }.take(1000)
println(toList.size) // 670
val sequence = generateSequence(2) { value -> value + 1 }.filter { it.isPrime() }.take(1000)
println(sequence.toList().size) // 1000
}
通过使用 Sequence
,你可以高效地处理大量数据或无限序列,而不需要一次性加载所有数据到内存中。这对于性能敏感的应用程序非常有用。
8.互操作性与可空性
互操作性是指不同系统、软件或编程语言之间能够无缝协作的能力。对于 Kotlin 来说,这意味着 Kotlin 代码可以轻松地与用其他语言(如 Java)编写的代码一起工作。
public class Jhava {
@NotNull
public String getHello() {
return "Hello World";
}
@Nullable
public String determineFriendShipLevel(){
return null;
}
}
fun main() {
val adversary = Jhava()
println(adversary.hello)
val level = adversary.determineFriendShipLevel()
println(level?.toLowerCase())
}
9.类型映射
代码运行时,所有的映射类型都会重新映射回对应的Java类型。
println(adversary.hitPoints.javaClass) // int
10.属性访问
不需要调用相关的setter方法,可以使用赋值语句来设置一个Java字段值。
11.@JvmName
@JvmName
是 Kotlin 提供的一个注解,用于在生成的 Java 字节码中指定方法或属性的具体名称。这在你需要控制 Kotlin 代码生成的 Java 方法名时非常有用,特别是在与 Java 代码互操作的情况下。
public static void main(String[] args) {
System.out.println(Hero.makeProclamation());
}
@file:JvmName("Hero")
fun main() {
val adversary = Jhava()
println(adversary.hello)
val level = adversary.determineFriendShipLevel()
println(level?.toLowerCase())
println(adversary.hitPoints.javaClass) // int
}
fun makeProclamation() = "Greeting,beast!"
12.@JvmField
@JvmField
是 Kotlin 提供的一个注解,用于在生成的 Java 字节码中直接暴露一个属性为字段(field),而不是通过 getter 和 setter 方法。这在你需要与 Java 代码进行互操作时特别有用,因为它允许 Java 代码直接访问 Kotlin 属性,就像访问普通字段一样。
class Spellbook {
@JvmField
val spells = listOf("Magic Ms. L","Lay on hans")
}
public static void main(String[] args) {
Spellbook spellbook = new Spellbook();
for (String spell : spellbook.spells){
System.out.println(spell);
}
}
13.@JvmOverloads
@JvmOverloads
是 Kotlin 提供的一个注解,用于生成具有默认参数值的方法的多个重载版本。在 Java 中,方法不支持默认参数,因此 Kotlin 会为每个可能的参数组合生成一个单独的方法。这使得 Kotlin 的默认参数功能可以与 Java 代码无缝集成。
@JvmOverloads
fun handOverFood(leftHand : String = "berrriea", rightHand : String = "beef"){
println("$leftHand and $rightHand")
}
14.@JvmStatic
1.单例模式:
当你实现单例模式时,可以使用 @JvmStatic 来提供一个静态的方法来获取单例实例。
object Singleton {
@JvmStatic
fun getInstance(): Singleton = this
}
// Java 代码
public class Main {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
// 使用 singleton
}
}
2.工具类
在工具类中,你可以使用 @JvmStatic 来定义静态方法,这样 Java 代码可以直接调用这些方法而不需要创建类的实例。
object StringUtils {
@JvmStatic
fun isNullOrEmpty(str: String?): Boolean {
return str == null || str.isEmpty()
}
@JvmStatic
fun reverse(str: String): String {
return str.reversed()
}
}
// Java 代码
public class Main {
public static void main(String[] args) {
boolean isEmpty = StringUtils.isNullOrEmpty("test");
String reversed = StringUtils.reverse("hello");
// 使用结果
}
}
3.伴生对象
在 Kotlin 中,伴生对象(companion object)中的成员默认不是静态的。使用 @JvmStatic 可以使这些成员在 Java 中表现为静态成员。
class Spellbook {
@JvmField
val spells = listOf("Magic Ms. L","Lay on hans")
companion object {
@JvmStatic
val MAX_SPELL_COUNT = 10
fun getSpellbookGreeting() = println("I am the Great Grimoire!")
}
}
System.out.println(Spellbook.getMAX_SPELL_COUNT());
Spellbook.Companion.getSpellbookGreeting();
4.枚举类
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF);
companion object {
@JvmStatic
fun fromInt(rgb: Int): Color? {
for (color in values()) {
if (color.rgb == rgb) {
return color
}
}
return null
}
}
}
// Java 代码
public class Main {
public static void main(String[] args) {
Color color = Color.fromInt(0xFF0000);
// 使用 color
}
}
13.@Throws
@Throws
是 Kotlin 中的一个注解,用于声明一个函数可能会抛出哪些受检异常(checked exceptions)。在 Java 中,受检异常必须在方法签名中声明,而在 Kotlin 中,由于语言设计的原因,默认情况下不需要声明受检异常。然而,在某些情况下,特别是当你的 Kotlin 代码需要与 Java 代码互操作时,使用 @Throws
注解可以明确地指出一个函数可能抛出的异常类型。
import java.io.File
import java.io.IOException
fun readFile(filePath: String): String {
val file = File(filePath)
return file.readText()
}
在这个例子中,readText() 方法可能会抛出 IOException。为了明确这一点,你可以使用 @Throws 注解:
import java.io.File
import java.io.IOException
@Throws(IOException::class)
fun readFile(filePath: String): String {
val file = File(filePath)
return file.readText()
}
如果你希望这个函数能够在 Java 代码中被调用,并且 Java 代码能够捕获 IOException,那么使用 @Throws 是必要的:
public class Main {
public static void main(String[] args) {
try {
String content = ExampleKt.readFile("path/to/file.txt");
System.out.println(content);
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:
@Throws
注解只适用于受检异常(checked exceptions)。对于运行时异常(unchecked exceptions),如 NullPointerException 或 IllegalArgumentException,不需要使用@Throws
注解。- 如果一个函数可能会抛出多种类型的受检异常,可以在 @Throws 注解中列出所有可能的异常类型
@Throws(IOException::class, FileNotFoundException::class)
fun readFile(filePath: String): String {
// 实现
}