目录

Java 与 Kotlin 对比学习指南(二)

以下是一份 超详细的 Java 与 Kotlin 对比学习指南,涵盖语法、设计理念和实际场景的深度对比,帮助您从 Java 平滑过渡到 Kotlin。


一、基础语法对比

1. 程序入口

Java
java 复制代码
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}
  • 必须定义 public static void main 方法。
  • 类名必须与文件名一致。
Kotlin
kotlin 复制代码
fun main() {
    println("Hello, Kotlin!")
}
// 或带参数
fun main(args: Array<String>) {
    println(args.joinToString())
}
  • 无需类包装,直接定义 main 函数。
  • println 是 Kotlin 标准库函数,无需 System.out

2. 变量声明

Java
java 复制代码
final String name = "Java";  // 不可变
int age = 25;               // 可变
Integer nullableAge = null; // 可空包装类型
  • 使用 final 声明常量。
  • 基本类型(int)不能为 null,需用包装类型(Integer)。
Kotlin
kotlin 复制代码
val name = "Kotlin"        // 不可变(类型推断为 String)
var age = 25               // 可变
var nullableAge: Int? = null // 可空类型(显式声明)
  • val 类似 finalvar 可变。
  • 类型后加 ? 表示可空,编译时强制检查。

3. 函数定义

Java
java 复制代码
public int sum(int a, int b) {
    return a + b;
}
// 重载
public int sum(int a, int b, int c) {
    return a + b + c;
}
  • 必须指定返回类型和访问修饰符(如 public)。
  • 重载需手动编写多个方法。
Kotlin
kotlin 复制代码
fun sum(a: Int, b: Int) = a + b  // 单行表达式
fun sum(a: Int, b: Int, c: Int = 0) = a + b + c // 默认参数
  • 支持表达式函数(省略 {}return)。
  • 默认参数减少重载需求。

二、面向对象对比

1. 类与构造函数

Java
java 复制代码
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // getter/setter 省略...
}
  • 字段通常私有,需手动生成构造方法和 getter/setter。
Kotlin
kotlin 复制代码
class Person(val name: String, var age: Int) // 主构造函数
  • val 生成只读属性(只有 getter),var 生成可变属性(getter/setter)。
  • 主构造函数直接声明属性。

2. 继承与接口

Java
java 复制代码
public class Animal {
    public void eat() { ... }
}
public class Dog extends Animal {
    @Override
    public void eat() { ... }
}
  • 使用 extendsimplements 关键字。
  • 默认类可继承(除非用 final 修饰)。
Kotlin
kotlin 复制代码
open class Animal {  // 必须用 open 允许继承
    open fun eat() { ... } // 允许重写的方法需 open
}
class Dog : Animal() {
    override fun eat() { ... }
}
  • 类和方法默认 final,需显式标记 open 才能继承/重写。
  • 使用 : 替代 extends/implements

3. 数据类

Java
java 复制代码
public class User {
    private int id;
    private String name;
    // 需手动实现 equals(), hashCode(), toString()
    // 或使用 Lombok @Data
}
  • 需手动编写或依赖 Lombok。
Kotlin
kotlin 复制代码
data class User(val id: Int, val name: String)
  • 自动生成 equals()hashCode()toString()copy() 等。

三、空安全机制对比

1. 可空性处理

Java
java 复制代码
String str = null; // 允许
int length = str.length(); // 运行时 NullPointerException
  • 无编译时检查,依赖注解(如 @Nullable)或手动判空。
Kotlin
kotlin 复制代码
var str: String? = null // 必须显式声明可空
val length = str?.length // 安全调用(返回 Int?)
val nonNullLength = str!!.length // 非空断言(可能抛 NPE)
val safeLength = str?.length ?: 0 // Elvis 操作符
  • 编译时强制检查可空性,减少运行时 NullPointerException

四、集合操作对比

1. 集合创建

Java
java 复制代码
List<String> list = Arrays.asList("a", "b", "c");
list.add("d"); // 抛出 UnsupportedOperationException(不可变)
List<String> mutableList = new ArrayList<>(list);
Kotlin
kotlin 复制代码
val list = listOf("a", "b", "c")  // 不可变
val mutableList = mutableListOf("a", "b") // 可变

2. 集合操作

Java
java 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<Integer> evens = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
Kotlin
kotlin 复制代码
val numbers = listOf(1, 2, 3)
val evens = numbers.filter { it % 2 == 0 } // 更简洁

五、函数式编程对比

1. Lambda 表达式

Java
java 复制代码
Runnable task = () -> System.out.println("Running");
Collections.sort(list, (a, b) -> a.compareTo(b));
Kotlin
kotlin 复制代码
val task = { println("Running") }
list.sortedBy { it } // 更自然的语法

2. 高阶函数

Java
java 复制代码
public interface Operation {
    int execute(int a, int b);
}
public int calculate(int a, int b, Operation op) {
    return op.execute(a, b);
}
// 调用
calculate(2, 3, (a, b) -> a + b);
Kotlin
kotlin 复制代码
fun calculate(a: Int, b: Int, op: (Int, Int) -> Int) = op(a, b)
// 调用
calculate(2, 3) { x, y -> x + y }

六、并发编程对比

1. 线程 vs 协程

Java
java 复制代码
new Thread(() -> {
    try {
        Thread.sleep(1000);
        System.out.println("Done");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();
Kotlin
kotlin 复制代码
GlobalScope.launch {
    delay(1000L) // 挂起函数,不阻塞线程
    println("Done")
}

七、扩展机制对比

1. 扩展函数

Java

无法直接扩展类,需通过工具类:

java 复制代码
public class StringUtils {
    public static String reverse(String s) {
        return new StringBuilder(s).reverse().toString();
    }
}
String reversed = StringUtils.reverse("hello");
Kotlin
kotlin 复制代码
fun String.reverse() = this.reversed()
val reversed = "hello".reverse()

八、与 Java 互操作

1. 调用 Java 代码

Kotlin 可直接使用 Java 类和库:

kotlin 复制代码
val javaList = ArrayList<String>() // Java 的 ArrayList
javaList.add("Kotlin")

2. Java 调用 Kotlin

  • Kotlin 的 顶级函数 在 Java 中通过生成的类调用:

    java 复制代码
    // Kotlin 文件:Utils.kt
    fun log(message: String) { ... }
    
    // Java 调用
    UtilsKt.log("Hello");
  • 伴生对象:

    java 复制代码
    // Kotlin
    class MyClass {
        companion object {
            fun create() = MyClass()
        }
    }
    
    // Java 调用
    MyClass.Companion.create();

九、关键总结

特性 Java Kotlin
变量声明 final + 类型显式 val/var + 类型推断
空安全 需手动检查或注解 编译时强制检查(?!!
函数式编程 Stream API(Java 8+) 原生支持(Lambda、扩展函数)
数据类 手动编写或 Lombok data class 自动生成
并发 线程/ExecutorService 协程(轻量级线程)
扩展机制 静态工具类 扩展函数/属性
与 Java 互操作 天然兼容 100% 兼容,但需注意空安全注解

十、迁移建议

  1. 从工具类开始:将 Java 工具类逐步改为 Kotlin 扩展函数。
  2. 优先迁移数据类 :用 data class 替代 Java Bean。
  3. 逐步引入空安全 :在混合代码中使用 @Nullable/@NotNull 注解。
  4. 尝试协程:替换简单的异步任务(如网络请求)。

通过对比学习,可以更深入理解 Kotlin 的设计哲学,写出更简洁、安全的代码!

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
mghio5 小时前
Dubbo 中的集群容错
java·微服务·dubbo
咖啡教室10 小时前
java日常开发笔记和开发问题记录
java
咖啡教室10 小时前
java练习项目记录笔记
java
鱼樱前端11 小时前
maven的基础安装和使用--mac/window版本
java·后端
RainbowSea11 小时前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq
RainbowSea11 小时前
5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
java·消息队列·rabbitmq
我不会编程55513 小时前
Python Cookbook-5.1 对字典排序
开发语言·数据结构·python
李少兄13 小时前
Unirest:优雅的Java HTTP客户端库
java·开发语言·http
此木|西贝13 小时前
【设计模式】原型模式
java·设计模式·原型模式