2012-05-04 38 views
16

Người ta nói rằng cơ chế tuần tự mặc định của Java không hiệu quả lắm vì a) nó phát hiện ra các trường để ghi/đọc qua phản xạ thường chậm b) nó ghi thêm dữ liệu để truyền.Java: hiệu quả của writeObject vs writeExternal

Một cách để làm cho nó hiệu quả hơn là triển khai Externalizable và các phương thức writeExternal/readExternal của nó. Đây là câu hỏi: nếu tôi thay vào đó cung cấp phương thức 'writeObject/readObject' và không gọi deafiltWriteObject/defaultReadObject trong đó, thì cơ chế này sẽ không sử dụng sự phản chiếu để tìm ra các trường để viết/đọc, cộng với nó đã thắng 't viết thêm dữ liệu để dòng (hoặc sẽ nó? không chắc chắn). Vì vậy, từ một quan điểm hiệu quả, đang thực hiện writeObject/readObject được đề cập ở trên giống như thực hiện Externalizable? Hay tùy chọn thứ hai cung cấp một số lợi ích thiết thực hơn mà trước đây không?

EDIT: sự khác biệt, ofcourse, là khi một lớp Serializable thực hiện readObject/writeObject được phân lớp và nếu lớp con có readObject/writeObject riêng của nó, chúng không cần gọi superO readObject/writeObject của siêu. Không phải như vậy nếu siêu/subclass thay vì thực hiện Externalizable. Trong trường hợp này, siêu của writeExternal/readExternal cần được gọi một cách rõ ràng. Tuy nhiên, sự khác biệt này không liên quan từ quan điểm hiệu quả.

Trả lời

7

Vẫn còn một số người đứng đầu trong việc chọn lớp/writeObject/readObject để gọi tiếp theo. nhưng nó giảm đáng kể.

Điều này có thể thực hiện giống như Externalizable tùy thuộc vào những gì bạn đang làm và liệu bạn có sử dụng các tùy chọn bổ sung mà nó cung cấp cho bạn hay không. ví dụ. readObject giả sử bạn tạo một đối tượng mới mỗi lần, Externalizable có readResolve có nghĩa là bạn có thể tái sử dụng các đối tượng.

http://docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/input.html

Trong nhiều trường hợp, các đối tượng tái chế là "bên cạnh" bước tăng tốc deserialization. (Giả sử đó là một lựa chọn cho bạn)

http://vanillajava.blogspot.co.uk/2011/10/recycling-objects-to-improve.html

+0

Bạn có thể pl. giải thích điều này nhiều hơn một chút: "Vẫn còn một số người đứng đầu trong việc chọn lớp/writeObject/readObject để gọi tiếp theo." Ngoài ra, 'readResolve' không phải là một phần của hợp đồng 'Externalizable', phải không?Vì vậy, tôi là một chút bối rối. – shrini1000

+0

Nó phải xác định lớp nào để gọi readObject hoặc readExternal trừ khi bạn cũng tự làm điều này. readResolve là một phương thức tùy chọn mà bạn có thể sử dụng với Serailizable. Xem liên kết đầu tiên để biết thêm chi tiết. –

+1

Thx. Tôi đã sử dụng readResolve, nhưng đã bị nhầm lẫn bởi vì bạn đã đề cập nó trong kết nối với Externalizable. Btw, tôi đọc bài viết của bạn. Tốt nhất. Tôi đã hỏi một câu hỏi ở đó. Nó sẽ tuyệt vời nếu bạn có thể pl. Đáp lại. – shrini1000

1

Tìm thấy một vài điều trong khi thử nghiệm và đi qua mã cơ chế serialization của:

1) nếu đối tượng được tìm thấy là Externalizable, nó đúc để Externalizable và phương thức tương ứng được gọi trên nó; trong khi đối tượng Serializable, nó được kiểm tra một cách phản xạ nếu nó có readObject/writeObject. Vì vậy, có thể điều này làm cho nó hơi chậm hơn,

2) lượng dữ liệu được viết cho Externalizable là một chút ít hơn Serializable với readObject/writeObject (Tôi tìm thấy một sự khác biệt của 1 byte cho mã sau khi tôi đã viết đối tượng B) .

Đối Externalizable:

static class A implements Externalizable 
{ 
    @Override 
    public void writeExternal(ObjectOutput out) throws IOException 
    { 
     System.out.println("A write called"); 
    } 

    @Override 
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException 
    { 
     System.out.println("A read called"); 
    }  
} 

static class B extends A implements Externalizable 
{  
    @Override 
    public void writeExternal(ObjectOutput out) throws IOException 
    { 
     super.writeExternal(out); 
     System.out.println("B write called"); 
    } 

    @Override 
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException 
    { 
     super.readExternal(in); 
     System.out.println("B read called"); 
    }  
} 

Đối Serializable:

static class A implements Serializable 
{ 
    private void writeObject(ObjectOutputStream out) throws IOException 
    { 
     System.out.println("A write called"); 
    } 

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException 
    { 
     System.out.println("A read called"); 
    }  
} 

static class B extends A implements Serializable 
{  
    private void writeObject(ObjectOutputStream out) throws IOException 
    {   
     System.out.println("B write called"); 
    } 

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException 
    {   
     System.out.println("B read called"); 
    }  
} 
2

Sự khác biệt lớn, về mặt thiết kế lớp, là Serializable sẽ làm việc trên bất kỳ lớp, trong khi Externalizable chỉ hoạt động trên các lớp học có thể thay đổi với các nhà thầu mặc định công cộng (no-arg).

+0

Họ có thực sự cần phải có thể thay đổi được không? Ý tôi là, tôi không thể làm một cái gì đó như thế này? http://www.byteslounge.com/tutorials/java-externalizable-example – shrini1000

+0

@ shrini1000, bạn có thể làm điều đó, nhưng lớp 'Người dùng' không phải là chủ đề an toàn. Tuy nhiên làm cho tất cả các trường 'dễ bay hơi' nên sửa lỗi đó, do đó, cuối cùng, bạn nói đúng, lớp học không, nói đúng, phải có thể thay đổi được. – nilskp

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