一、变量与常量
1.1 基本声明对比
// Java
String name = "Java";
final int MAX_COUNT = 100; // 常量
// Swift
var name = "Swift" // 可变变量(类型推断为String)
let maxCount = 100 // 常量(类型推断为Int)
核心差异
- 类型后置:Swift 支持显式类型标注 var age: Int = 25,但通常使用类型推断
- 不可变性优先级:优先使用 let(类似Java final),var 仅在需要时使用
- 类型严格性:Swift 是强类型语言,var x = 1 之后不能赋值为字符串
1.2 基础数据类型
Java | Swift | 说明 |
int | Int | 统一大小写 |
double | Double | |
boolean | Bool | 值必须为 true/false |
char | Character | Unicode 字符 |
String | String | 值类型(Swift中为结构体) |
代码示例
let isActive: Bool = true // 明确类型标注
var temperature = 36.5 // 推断为Double
let emoji: Character = "" // 单个字符
二、字符串处理
2.1 字符串插值
// Java
String name = "Tim";
int age = 30;
System.out.println("Name: " + name + ", Age: " + age);
// Swift
let name = "Tim"
let age = 30
print("Name: \(name), Age: \(age)") // 直接嵌入表达式
优势
- 支持任意表达式:print("Next year: \(age + 1)")
- 自动类型转换:无需显式调用 toString()
三、可选类型(Optionals)
3.1 本质对比
// Java Optional
Optional optionalName = Optional.ofNullable(getName());
String name = optionalName.orElse("Unknown");
// Swift Optionals
var optionalName: String? = getName()
let name = optionalName ?? "Unknown" // 空合并运算符
关键差异
- 语法深度集成:Swift 用 ? 直接标记可选类型,而非泛型包装器
- 强制解包风险:let value = optionalName!(类似Java optionalName.get())
- 可选绑定:安全解包方式
if let safeName = optionalName {
print("Name is \(safeName)")
}
四、集合类型
4.1 数组对比
// Java ArrayList
List numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
int first = numbers.get(0);
// Swift Array
var numbers = [1, 2] // 类型推断为[Int]
numbers.append(3) // 添加元素
let first = numbers[0] // 访问元素
4.2 字典对比
// Java HashMap
Map ages = new HashMap<>();
ages.put("Alice", 30);
int aliceAge = ages.get("Alice");
// Swift Dictionary
var ages = ["Alice": 30, "Bob": 28] // 类型推断为[String: Int]
ages["Charlie"] = 25 // 添加键值对
let aliceAge = ages["Alice"] ?? 0 // 返回Optional值
核心特性
- 值类型语义:Swift 集合类型是结构体,赋值时复制(Copy-on-Write优化)
- 类型统一:[Int] 等价于 Array
,[String: Int] 等价于 Dictionary
五、控制流
5.1 循环语句
// Java for循环
for (int i=0; i<5; i++) {
System.out.println(i);
}
for (String name : names) {
System.out.println(name);
}
// Swift for-in
for i in 0..<5 { // 半开区间(不包含5)
print(i)
}
for name in names {
print(name)
}
// 带步长
for i in stride(from: 0, to: 10, by: 2) {
print(i) // 0,2,4,6,8
}
5.2 Switch语句
// Java switch
int value = 2;
switch (value) {
case 1: System.out.println("One"); break;
case 2: System.out.println("Two"); break;
default: System.out.println("Other");
}
// Swift switch(更强大)
let value = 2
switch value {
case 1, 3, 5: // 复合匹配
print("Odd")
case 2...4: // 区间匹配
print("Even")
case let x where x > 10: // Where条件
print("Large")
default:
break // 必须穷举所有可能
}
六、函数与闭包
6.1 函数定义对比
// Java方法
public static int add(int a, int b) {
return a + b;
}
// Swift函数
func add(_ a: Int, b: Int) -> Int {
return a + b
}
// 调用:add(5, b: 3) → 参数标签设计
关键特性
- 参数标签:支持外部标签与内部名称分离
func sendMessage(to recipient: String, from sender: String) { ... }
sendMessage(to: "Alice", from: "Bob")
- 元组返回:
func getPoint() -> (x: Int, y: Int) {
return (10, 20)
}
let point = getPoint()
print(point.x) // 10
6.2 闭包 vs Lambda
// Java Lambda
List numbers = Arrays.asList(1,2,3);
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
// Swift闭包
let numbers = [1,2,3]
numbers.filter { $0 % 2 == 0 }
.forEach { print($0) }
// 完整闭包语法
numbers.sorted(by: { (a: Int, b: Int) -> Bool in
return a > b
})
闭包特性
- 尾随闭包:当闭包是最后一个参数时,可写在括号外
- 简写参数:$0 表示第一个参数
- 逃逸闭包:用 @escaping 标记可能异步执行的闭包
七、错误处理
7.1 对比体系
// Java受检异常
public void readFile() throws IOException {
// 可能抛出异常的操作
}
// Swift错误处理
enum FileError: Error {
case notFound
case permissionDenied
}
func readFile() throws -> String {
guard exists else { throw FileError.notFound }
return "Content"
}
// 调用处
do {
let content = try readFile()
} catch FileError.notFound {
print("文件不存在")
} catch {
print("其他错误:\(error)")
}
关键区别
- 错误类型:Swift 错误是遵守 Error 协议的类型(通常是枚举)
- 不强制处理:除非使用 try! 或 try?,否则必须用 do-catch
- defer语句:类似Java finally
func processFile() {
let file = openFile()
defer { file.close() } // 在函数返回前执行
// 处理文件
}
上篇总结练习
// 综合练习:实现安全除法函数
func safeDivide(_ a: Double, _ b: Double) -> Double? {
guard b != 0 else {
return nil
}
return a / b
}
// 使用if-let解包
if let result = safeDivide(10, 2) {
print("结果:\(result)")
} else {
print("除数不能为零")
}