目录

一、空引用安全(Null Safety)

1. 什么是空引用?为什么危险?

2. 仓颉如何解决空引用问题?

3. 可选类型(Option )详解

4. 可选类型的语法糖

二、值类型(Value Types)

1. 什么是值类型?

2. 值类型 vs. 引用类型

3. 值类型的安全性优势

4. 用户自定义值类型

三、空引用安全与值类型的协同作用

总结


一、空引用安全(Null Safety)

1. 什么是空引用?为什么危险?
  • 空引用:在许多语言中(如 Java、C#),引用类型变量可以指向 null(表示 “无值”)。
    示例(Java 中的问题):
    String str = null;
    System.out.println(str.length()); // 运行时 NullPointerException
    
  • 风险:直接访问 null 的成员会导致崩溃(如 NullPointerException),是常见的编程错误。Tony Hoare 称其为 “价值十亿美元的错误”。
2. 仓颉如何解决空引用问题?
  • 非空引用类型:仓颉的普通引用类型永远不为 null,编译期强制检查。
    示例
    let str: String = null  // 编译错误:String 类型不能为 null
    
  • 可选类型(Option<T>):若需要表示 “可能为空”,使用 Option<T> 类型。
    示例
    let maybeStr: Option<String> = Some("hello")  // 有值
    let emptyStr: Option<String> = None          // 空值
3. 可选类型(Option<T>)详解
  • 本质Option<T> 是一个枚举(enum),有两种可能的值:
    • Some(value):包含实际值 value(类型为 T)。
    • None:表示空值。
  • 模式匹配:必须通过模式匹配或特定方法处理 Option<T>,确保非空时才访问值。
    示例
    let maybeNum: Option<Int> = Some(42)
    
    match maybeNum {
        Some(num) => println(num)  // 匹配成功,num 是 Int 类型
        None => println("为空")
    }
4. 可选类型的语法糖
  • 简写 ?T?T 是 Option<T> 的简写。
    let a: ?Int = Some(123)  // 等价于 Option<Int>
    
  • 可选链操作符 ?.:安全访问成员,若值为 None 则直接返回 None
    let maybeStr: ?String = Some("hello")
    let length: ?Int = maybeStr?.length()  // Some(5)
    
    let emptyStr: ?String = None
    let length2: ?Int = emptyStr?.length()  // None(不会崩溃)
    
  • 空合并操作符 ??:提供默认值,若左侧为 None 则使用右侧值。
    let a: ?Int = None
    let b = a ?? 123  // b = 123
    
    let c: ?Int = Some(456)
    let d = c ?? 123  // d = 456

二、值类型(Value Types)

1. 什么是值类型?
  • 值语义:变量保存的是数据本身,而非引用。赋值时会复制整个数据。
    对比引用类型:引用类型变量保存的是对象的内存地址,赋值只复制引用(共享对象)。
  • 示例(值类型的复制):
    struct Point {
        var x: Int
        var y: Int
    }
    
    let a = Point(x: 1, y: 2)
    let b = a  // 复制整个 Point 数据
    
    a.x = 10   // 修改 a 不影响 b
    println(b.x)  // 输出 1(b 是独立副本)
    
2. 值类型 vs. 引用类型
特性 值类型(如 struct) 引用类型(如 class)
数据存储 直接保存数据 保存引用(指向堆上的对象)
赋值行为 复制整个数据 复制引用,共享对象
修改影响 修改副本不影响原数据 修改一个引用会影响所有引用
内存位置 通常在栈上(或内联在对象中) 总是在堆上
典型例子 IntStringstruct class, 数组(部分语言)
3. 值类型的安全性优势
  • 并发安全:多线程中传递值类型时,每个线程获得独立副本,避免数据竞争(Data Race)。
    示例
    func process(point: Point) {
        // 在线程中修改 point,不会影响原始数据
        point.x += 1
    }
    
    let original = Point(x: 0, y: 0)
    // 传递副本到多个线程
    thread1.run { process(original) }
    thread2.run { process(original) }
    
  • 可预测性:值类型的修改不会意外影响其他部分的代码,使程序行为更清晰。
4. 用户自定义值类型

在仓颉中,使用 struct 定义值类型:

struct Person {
    let name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let alice = Person(name: "Alice", age: 30)
let bob = alice  // 复制整个 Person 数据
bob.age = 31     // 只修改 bob 的副本
println(alice.age)  // 输出 30(alice 未改变)

三、空引用安全与值类型的协同作用

  • 组合使用
    // 可选值类型:可能为空的 Point
    let maybePoint: ?Point = Some(Point(x: 0, y: 0))
    
    // 安全访问:若 maybePoint 为 None,整个表达式返回 None
    let xCoord: ?Int = maybePoint?.x
    
    // 使用空合并提供默认值
    let safeX = xCoord ?? -1  // 若 xCoord 为 None,返回 -1
    
  • 优势
    1. 空引用安全:通过类型系统强制处理空值,避免崩溃。
    2. 值类型安全:通过复制语义避免共享可变状态,提升并发安全性。

总结

  • 空引用安全:通过 Option<T> 强制显式处理空值,从类型系统层面消除 NullPointerException
  • 值类型:通过复制语义减少共享可变状态,提升程序可预测性和并发安全性。

 

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐