2015-01-10 11 views
11

Tôi biết lợi ích của các lĩnh vực lười biếng khi cần đánh giá giá trị hoãn lại vì một số lý do. Tôi đã tự hỏi hành vi của các lĩnh vực lười biếng về serialization là gì.Việc tuần tự hóa các trường lười hoạt động như thế nào?

Cân nhắc lớp học sau.

class MyClass { 
    lazy val myLazyVal = {...} 
    ... 
} 

Câu hỏi:

  • Nếu một thể hiện của MyClass là serialized, không lĩnh vực lười biếng được đăng quá?
  • Hành vi của việc tuần tự hóa có thay đổi nếu trường đã được truy cập hay không trước khi tuần tự hóa? Ý tôi là, nếu tôi không gây ra sự đánh giá của trường, nó được coi là null?
  • Cơ chế tuần tự hóa có kích thích đánh giá tiềm ẩn về trường lười không?
  • Có cách nào đơn giản để tránh việc tuần tự hóa biến và nhận giá trị được tính toán lại thêm một lần nữa sau khi hủy tuần tự hóa không? Điều này sẽ xảy ra độc lập với việc đánh giá lĩnh vực này.
+0

gì làm bạn mea n bởi "serialization"? Tôi hy vọng bạn không sử dụng serialization java chuẩn trong scala. Bạn đang sử dụng thư viện tuần tự hóa nào? –

Trả lời

7

câu trả lời

  1. Yes nếu lĩnh vực đã được khởi tạo, nếu không bạn có thể bước đi nó như là một phương pháp. Giá trị không được tính -> không được tuần tự hóa, nhưng có sẵn sau khi de serialization.
  2. Nếu bạn không chạm vào lĩnh vực nó đăng gần như đó là một phương pháp 'def' đơn giản, bạn không cần nó gõ được serializable chính nó, nó sẽ được tính toán lại sau khi de-serialization
  3. Không
  4. Bạn có thể thêm @transient trước khi định nghĩa val lười biếng trong ví dụ mã của tôi, như tôi hiểu nó sẽ làm chính xác những gì bạn muốn

mã để chứng minh

object LazySerializationTest extends App { 

    def serialize(obj: Any): Array[Byte] = { 
    val bytes = new ByteArrayOutputStream() 
    val out = new ObjectOutputStream(bytes) 
    out.writeObject(obj) 
    out.close() 
    bytes.toByteArray 
    } 

    def deSerialise(bytes: Array[Byte]): MyClass = { 
    new ObjectInputStream(new ByteArrayInputStream(bytes)). 
     readObject().asInstanceOf[MyClass] 
    } 

    def test(obj: MyClass): Unit = { 
    val bytes = serialize(obj) 
    val fromBytes = deSerialise(bytes) 

    println(s"Original cnt = ${obj.x.cnt}") 
    println(s"De Serialized cnt = ${fromBytes.x.cnt}") 
    } 

    object X { 
    val cnt = new AtomicInteger() 
    } 

    class X { 
    // Not Serializable 
    val cnt = X.cnt.incrementAndGet 
    println(s"Create instance of X #$cnt") 
    } 

    class MyClass extends Serializable { 
    lazy val x = new X 
    } 

    // Not initialized 
    val mc1 = new MyClass 
    test(mc1) 

    // Force lazy evaluation 
    val mc2 = new MyClass 
    mc2.x 
    test(mc2) // Failed with NotSerializableException 

} 
+1

Chú ý: Đánh dấu trường lười là '@ transient' sẽ (có thể) không đánh dấu mặt nạ bit mà val lười biếng sử dụng nội bộ là' @ transient'. Do đó, chúng sẽ được sắp xếp theo thứ tự. Bạn sẽ kết thúc với một val lazylyizedized/unitialized val khi deserializing. – gzm0

+0

Tôi đã thử thêm tạm thời vào mã ở trên và có vẻ như hoàn toàn ổn. Tôi sẽ nói nếu mặt nạ không được đánh dấu là thoáng qua đó là lỗi scalac –

+0

Vâng, đó là một lỗi trong cả hai trường hợp sau đó. Mặt nạ có thể được chia sẻ giữa nhiều vals lười. Nếu một trong số họ là '@ transient' và người kia thì không, bạn sẽ làm gì? (Vâng, hành vi chính xác sẽ không được chia sẻ với họ sau đó. Thật không may tôi có nghi ngờ của tôi về điều đó). – gzm0

Các vấn đề liên quan