专业的JAVA编程教程与资源

网站首页 > java教程 正文

从Java到Swift学习指南(中篇)_java从何学起

temp10 2025-02-19 13:56:31 java教程 15 ℃ 0 评论

本章重点突破

Java开发者需要跨越的3大认知鸿沟

  1. 值类型优先的设计哲学(结构体>类)
  2. 协议的多维度扩展能力(超越接口)
  3. 面向协议编程范式(POP)的实践

一、结构体与类的抉择

(1) 基础语法对比

// Java类
public class Vehicle {
    private int wheels;
    
    public Vehicle(int wheels) {
        this.wheels = wheels;
    }
    
    public String description() {
        return "Vehicle with " + wheels + " wheels";
    }
}
// Swift结构体(默认初始化器)
struct Vehicle {
    let wheels: Int  // 不可变属性
    var color: String = "white"  // 默认值
    
    func description() -> String {
        return "Vehicle with \(wheels) wheels"
    }
}

// 使用差异点
let car = Vehicle(wheels: 4)  // 栈分配
car.color = "red"  // ?错误:结构体是值类型,let常量不可变
var truck = car    // 值拷贝产生新实例

(2) 核心差异表

特性

从Java到Swift学习指南(中篇)_java从何学起

Swift结构体

Swift类

Java类

类型性质

值类型(栈分配)

引用类型(堆分配)

引用类型(堆分配)

继承

不支持

单继承

单继承

内存管理

自动值拷贝

ARC引用计数

GC垃圾回收

线程安全

天然线程安全(独立拷贝)

需手动同步

需手动同步

拷贝行为

深拷贝

浅拷贝

浅拷贝

推荐使用场景

简单数据模型

需要继承/共享实例的场景

所有对象模型

(3) 实战选择策略

// ?优先使用结构体的情况
struct Point { var x, y: Double }  // 几何坐标
struct RGB { let r, g, b: UInt8 }  // 颜色值
struct Angle { var radians: Double } // 角度值

// 必须使用类的情况
class DatabaseConnection { /* 需要共享资源 */ } 
class WindowController: NSObject { /* 需要继承Cocoa类 */ }
class SharedState { /* 需要引用语义 */ }

二、协议(Protocol)的维度突破

(1) 基础协议对比

// Java接口
interface Flyable {
    int MAX_HEIGHT = 1000;  // 默认public static final
    void fly();             // 抽象方法
    default void land() {   // 默认实现
        System.out.println("Landing...");
    }
}
// Swift协议(协议扩展)
protocol Flyable {
    static var maxHeight: Int { get }  // 类型属性要求
    func fly()
    var altitude: Double { get set }   // 属性要求
}

extension Flyable {
    func land() {  // 协议扩展提供默认实现
        print("Landing...")
    }
}

struct Drone: Flyable {
    static let maxHeight = 500
    private(set) var altitude = 0.0  // 外部只读
    
    func fly() {
        altitude += 100
    }
}

(2) 协议进阶特性

特性1:关联类型(类似Java泛型但更灵活)

protocol Container {
    associatedtype Element
    var count: Int { get }
    mutating func append(_ item: Element)
    subscript(i: Int) -> Element { get }
}

struct IntStack: Container {
    typealias Element = Int  // 显式指定类型
    private var elements = [Int]()
    
    mutating func append(_ item: Int) {
        elements.append(item)
    }
    
    subscript(i: Int) -> Int {
        return elements[i]
    }
}

特性2:条件化扩展

extension Array: Container where Element: Equatable {
    func contains(_ element: Element) -> Bool {
        // 只有元素可比较时才获得此方法
        return self.contains(element)
    }
}

特性3:协议组合

func process(entity: Flyable & CustomStringConvertible) {
    // 同时遵守多个协议的对象
    entity.fly()
    print(entity.description)
}

三、扩展(Extension)的降维打击

(1) 基础扩展对比

// Java工具类模式
public final class StringUtils {
    public static String reverse(String s) {
        return new StringBuilder(s).reverse().toString();
    }
}

// 使用方式
String reversed = StringUtils.reverse("hello");
// Swift扩展语法
extension String {
    func reversed() -> String {
        return String(self.reversed())
    }
}

// 使用方式
let reversed = "hello".reversed()

(2) 协议扩展黑科技

// 为所有集合类型添加统计功能
extension Collection where Element: Numeric {
    var average: Double? {
        guard !isEmpty else { return nil }
        return Double(reduce(0, +)) / Double(count)
    }
}

let numbers = [1, 2, 3, 4, 5]
numbers.average // 3.0

四、枚举的次元突破

(1) 基础枚举对比

// Java枚举
enum Planet {
    MERCURY(3.303e+23),
    VENUS(4.869e+24);
    
    private final double mass;
    
    Planet(double mass) {
        this.mass = mass;
    }
    
    public double getMass() {
        return mass;
    }
}
// Swift枚举(关联值)
enum Planet {
    case mercury(mass: Double)
    case venus(mass: Double)
    
    var mass: Double {
        switch self {
        case .mercury(let mass), .venus(let mass):
            return mass
        }
    }
}

let earth = Planet.mercury(mass: 5.972e24)

(2) 模式匹配实战

enum NetworkResponse {
    case success(data: Data, code: Int)
    case failure(error: Error, retry: Bool)
}

func handle(response: NetworkResponse) {
    switch response {
    case .success(let data, 200..<300):
        processData(data)
    case .failure(let error, true):
        attemptRetry()
    case .failure(_, false):
        showErrorMessage()
    }
}

五、错误处理范式迁移

(1) 基础语法对比

// Java受检异常
public class FileParser {
    public String readFile(String path) throws IOException {
        return Files.readString(Paths.get(path));
    }
}

// 使用方式
try {
    String content = new FileParser().readFile("test.txt");
} catch (IOException e) {
    System.err.println("File error: " + e.getMessage());
}
// Swift错误处理
enum FileError: Error {
    case notFound
    case permissionDenied
}

struct FileParser {
    func readFile(path: String) throws -> String {
        guard FileManager.default.fileExists(atPath: path) else {
            throw FileError.notFound
        }
        return try String(contentsOfFile: path)
    }
}

// 使用方式
do {
    let content = try FileParser().readFile("test.txt")
} catch FileError.notFound {
    print("文件不存在")
} catch {
    print("未知错误: \(error)")
}

(2) 错误处理进阶技巧

技巧1:Result类型处理异步错误

func fetchData(completion: @escaping (Result) -> Void) {
    URLSession.shared.dataTask(with: url) { data, _, error in
        if let error = error {
            completion(.failure(error))
        } else if let data = data {
            completion(.success(String(data: data, encoding: .utf8)!))
        }
    }.resume()
}

// 使用方式
fetchData { result in
    switch result {
    case .success(let str): 
        print(str)
    case .failure(let error):
        print("请求失败: \(error)")
    }
}

技巧2:try? 与 try! 的合理使用

let content = try? readFile("test.txt")  // 返回可选类型
let sureContent = try! readFile("config.json")  // 确定不会出错时使用

六、内存管理哲学差异

(1) ARC vs GC对比表

特性

Swift ARC

Java GC

内存释放时机

引用计数归零立即释放

不定期由GC决定

系统开销

维护引用计数有固定开销

全堆扫描导致停顿

可预测性

内存释放时间确定

释放时间不可控

循环引用处理

需手动使用weak/unowned

自动检测并回收

线程安全

原子操作保证线程安全

需要同步机制

(2) 循环引用解决方案

class DataLoader {
    var onCompleted: (() -> Void)?  // 强引用
    
    func load() {
        // 模拟异步操作
        DispatchQueue.main.asyncAfter(deadline: .now()+1) {
            self.onCompleted?()  // 循环引用!
        }
    }
}

// 正确写法(使用weak)
func load() {
    DispatchQueue.main.asyncAfter(deadline: .now()+1) { [weak self] in
        self?.onCompleted?()  // 弱引用打破循环
    }
}

// 或者使用unowned(当确定对象一定存在时)
func load() {
    DispatchQueue.main.asyncAfter(deadline: .now()+1) { [unowned self] in
        self.onCompleted?()  // 无主引用
    }
}

本章关键练习

  1. 将Java类改写成Swift结构体,体会值类型特性
  2. 实现一个支持关联类型的容器协议
  3. 为现有类型(如Int)添加扩展方法
  4. 设计带有关联值的枚举处理网络状态
  5. 使用Result类型重构异步错误处理
  6. 分析并修复一个循环引用场景

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

欢迎 发表评论:

最近发表
标签列表