JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java开发者迁移到Kotlin指南(中篇)

wys521 2025-05-11 19:05:10 精选教程 17 ℃ 0 评论

1. 类与对象设计

1.1 类声明简化

基本类声明对比

// Java
public class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // getters/setters...
}
// Kotlin
class Person(val name: String, var age: Int)

关键差异

  • 主构造器直接写在类头
  • val/var参数自动生成属性和字段
  • 默认public可见性
  • 默认final类(不可继承)

1.2 数据类(Data Class)

POJO转换示例

// Java
public class User {
    private String username;
    private String email;
    
    // 构造器、getters、setters、equals、hashCode、toString...
    // 通常需要50+行代码
}
// Kotlin
data class User(val username: String, val email: String)
// 自动生成:equals()/hashCode()/toString()/copy()/componentN()

数据类特性

  • 自动生成标准方法
  • 解构声明支持:val (name, email) = user // 自动分解为组件
  • copy方法用于不可变对象的修改:val updatedUser = user.copy(email = "new@email.com")

1.3 单例对象(Object Declaration)

单例模式对比

// Java
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
// Kotlin
object Singleton {
    fun doSomething() { ... }
}
// 使用:Singleton.doSomething()

伴生对象(Companion Object)

class MyClass {
    companion object {
        const val CONSTANT = "value"
        
        fun factory() = MyClass()
    }
}
// 使用:MyClass.CONSTANT 或 MyClass.factory()

2. 继承与接口

2.1 继承体系

基本继承语法

open class Animal(val name: String) {  // 必须标记open才能被继承
    open fun makeSound() { ... }      // 必须标记open才能被重写
}

class Dog(name: String) : Animal(name) {
    override fun makeSound() {
        super.makeSound()
        println("Bark!")
    }
}

与Java的关键差异

  1. 默认final类(必须显式声明open才能继承)
  2. 使用冒号(:)代替extends/implements
  3. 主构造器调用必须立即发生

2.2 接口增强

带默认方法的接口

interface Clickable {
    fun click()  // 抽象方法
    fun showOff() = println("I'm clickable!")  // 默认实现
}

interface Focusable {
    fun showOff() = println("I'm focusable!")
}

class Button : Clickable, Focusable {
    override fun click() = println("Clicked")
    
    // 必须解决接口冲突
    override fun showOff() {
        super<Clickable>.showOff()
        super<Focusable>.showOff()
    }
}

接口属性

interface User {
    val nickname: String  // 抽象属性
    val email: String
        get() = "$nickname@example.com"  // 提供getter实现
}

3. 属性与字段

3.1 属性声明

完整属性语法

class Person(name: String) {
    var name: String = name
        get() = field.capitalize()  // 后备字段(field)
        set(value) {
            if (value.isNotBlank()) field = value
        }
}

与Java Bean的对应关系

  • var自动生成getter/setter
  • val只生成getter
  • 自定义访问器提供额外逻辑

3.2 延迟初始化

lateinit var

class MyTest {
    lateinit var service: Service  // 不能是原始类型
    
    @Before fun setUp() {
        service = Service()  // 延迟初始化
    }
    
    @Test fun test() {
        if (::service.isInitialized) {  // 反射检查
            service.doSomething()
        }
    }
}

惰性初始化(by lazy)

val heavyObject: HeavyObject by lazy {
    println("Initializing...")
    HeavyObject()  // 首次访问时初始化
}

4. 扩展函数与属性

4.1 扩展函数

集合操作示例

fun <T> List<T>.penultimate(): T {
    if (size < 2)
        throw NoSuchElementException()
    return this[size - 2]
}

// 使用
val list = listOf(1, 2, 3)
println(list.penultimate())  // 输出2

Java调用扩展函数

// Java中调用Kotlin扩展函数
ListUtilKt.penultimate(list);

4.2 扩展属性

实现示例

val String.lastChar: Char
    get() = get(length - 1)

var StringBuilder.lastChar: Char
    get() = get(length - 1)
    set(value) = setCharAt(length - 1, value)

注意事项

  • 不能有后备字段
  • 实际上是语法糖(编译为静态方法)
  • 作用域控制很重要(避免污染全局命名空间)

5. 集合API

5.1 集合体系结构

Kotlin集合层次

  • IterableMutableIterable
  • CollectionMutableCollection
  • List/Set/MapMutableList/MutableSet/MutableMap

创建集合

val readOnlyList = listOf(1, 2, 3)
val mutableList = mutableListOf(1, 2, 3)
val map = mapOf(1 to "one", 2 to "two")

5.2 函数式操作

常用操作符

val numbers = listOf(1, 2, 3, 4)

// 转换
numbers.map { it * 2 }  // [2, 4, 6, 8]
numbers.flatMap { listOf(it, it) }  // [1,1,2,2,3,3,4,4]

// 过滤
numbers.filter { it % 2 == 0 }  // [2, 4]
numbers.filterNot { it % 2 == 0 }  // [1, 3]

// 聚合
numbers.reduce { acc, i -> acc + i }  // 10
numbers.fold(10) { acc, i -> acc + i }  // 20

// 查找
numbers.find { it > 2 }  // 3
numbers.firstOrNull { it > 5 }  // null

序列(Sequence)优化

list.asSequence()
    .filter { it % 2 == 0 }
    .map { it * 2 }
    .toList()  // 延迟计算,避免中间集合创建

6. 泛型系统

6.1 声明处型变(Declaration-site Variance)

in/out修饰符

interface Producer<out T> {  // 协变
    fun produce(): T
}

interface Consumer<in T> {   // 逆变
    fun consume(item: T)
}

// 使用
val producer: Producer<Animal> = Producer<Dog>()
val consumer: Consumer<Dog> = Consumer<Animal>()

6.2 类型投影(Use-site Variance)

Java通配符对应

// Kotlin
fun copy(from: Array<out Any>, to: Array<Any>) { ... }

// 相当于Java的
void copy(Array<? extends Object> from, Array<Object> to)

星投影(Star Projection)

fun printSize(list: List<*>) {
    println(list.size)  // 可以调用不依赖类型参数的方法
}

7. 函数式编程

7.1 Lambda表达式

语法简化

// 完整形式
val sum = { x: Int, y: Int -> x + y }

// 类型推断
val sum: (Int, Int) -> Int = { x, y -> x + y }

// 单参数隐式it
list.filter { it % 2 == 0 }

SAM转换

// Java接口
interface Runnable {
    void run();
}

// Kotlin使用
val runnable = Runnable { println("Running") }

7.2 高阶函数

函数作为参数

fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
    return operation(x, y)
}

// 调用
calculate(2, 3, { a, b -> a * b })  // 6
calculate(2, 3) { a, b -> a + b }   // 5 (尾随lambda)

返回函数

fun operationSelector(op: String): (Int, Int) -> Int {
    return when (op) {
        "+" -> { a, b -> a + b }
        "*" -> { a, b -> a * b }
        else -> throw IllegalArgumentException()
    }
}

// 使用
val add = operationSelector("+")
println(add(2, 3))  // 5

7.3 内联函数

性能优化

inline fun <T> lock(lock: Lock, body: () -> T): T {
    lock.lock()
    try {
        return body()
    } finally {
        lock.unlock()
    }
}

// 调用处会内联展开,避免lambda对象创建

限制

  • 内联函数不能递归
  • 公有API的内联函数不能使用非公有API
  • 参数不能存储在字段中

8. 作用域函数

8.1 五种作用域函数对比

函数

上下文对象引用

返回值

典型使用场景

let

it

lambda结果

非空对象处理

run

this

lambda结果

对象配置计算

with

this

lambda结果

对象分组调用

apply

this

对象本身

对象初始化

also

it

对象本身

附加效果

8.2 使用示例

对象初始化链

val dialog = AlertDialog.Builder(context).apply {
    setTitle("Warning")
    setMessage("Are you sure?")
    setPositiveButton("OK") { _, _ -> }
    setNegativeButton("Cancel", null)
}.create()

数据处理管道

val result = input?.let { 
    it.trim() 
}?.takeIf { 
    it.isNotEmpty() 
}?.run { 
    parse(this) 
} ?: defaultValue

9. 委托模式

9.1 类委托

实现模式

interface Database {
    fun save(data: String)
}

class RealDatabase : Database {
    override fun save(data: String) { /*...*/ }
}

class ProxyDatabase(db: Database) : Database by db  // 自动转发所有方法

9.2 属性委托

内置委托

// 惰性初始化
val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}

// 观察属性变化
var observed: String by Delegates.observable("初始值") { 
    prop, old, new ->
    println("$old -> $new")
}

自定义委托

class StringDelegate(private var value: String) {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        println("读取 ${property.name}")
        return value
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("设置 ${property.name} = $value")
        this.value = value
    }
}

// 使用
var str by StringDelegate("默认值")
str = "新值"  // 日志:设置 str = 新值
println(str)  // 日志:读取 str → 输出"新值"

10. 注解与反射

10.1 常用注解

互操作注解

  • @JvmStatic:生成静态方法
  • @JvmOverloads:生成重载方法
  • @JvmField:暴露为字段(而非属性)

空安全注解

// Java
public @Nullable String getName() { ... }
public @NotNull String getRequiredName() { ... }

// Kotlin调用
val name = javaObj.name  // String?
val required = javaObj.requiredName  // String

10.2 反射API

基本用法

class Person(val name: String, var age: Int)

fun reflect() {
    val person = Person("Alice", 25)
    val kClass = person::class
    
    // 获取属性
    val ageProp = kClass.memberProperties.find { it.name == "age" }
    if (ageProp is KMutableProperty<*>) {
        ageProp.setter.call(person, 26)
    }
    
    println(person.age)  // 26
}

与Java反射互操作

val javaClass = person.javaClass
val kotlinClass = javaClass.kotlin  // 转换回Kotlin反射API

11. Java互操作深入

11.1 类型映射

特殊类型处理

  • void → Unit
  • Java原始类型 → Kotlin非空类型(int → Int)
  • Java集合类型 → Kotlin平台类型(List → (Mutable)List<String!>!)

数组处理

// Java方法:public String[] getNames()
val names = javaObj.names  // Array<String>!(平台类型)
val first = names[0]       // String!(平台类型)

// 原始类型数组
val intArray = javaObj.intArray  // IntArray!(对应Java的int[])

11.2 异常处理差异

受检异常处理

// Java方法:public void write() throws IOException
fun writeSafely() {
    try {
        javaObj.write()
    } catch (e: IOException) {  // 不是必须捕获
        // 处理异常
    }
}

结语

中篇深入探讨了Kotlin在面向对象和函数式编程方面的特性,展示了如何用更简洁的语法实现更强大的抽象。这些特性包括:

  • 数据类和单例对象的声明简化
  • 扩展函数对现有类的无侵入式增强
  • 丰富的集合操作API
  • 灵活的函数式编程支持
  • 强大的委托模式

下篇将聚焦于协程、DSL构建、性能优化和实际迁移策略,帮助开发者完成从Java到Kotlin的完整过渡。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表