Khi chúng tôi tuần tự hóa các đối tượng, các thành viên tĩnh không được tuần tự hóa, nhưng nếu chúng ta cần làm như vậy, có cách nào không?Làm thế nào để tuần tự hóa các thành viên dữ liệu tĩnh của một lớp Java?
Trả lời
Câu hỏi đầu tiên là tại sao bạn cần phải tuần tự hóa các thành viên tĩnh?
Thành viên tĩnh được liên kết với lớp học, chứ không phải trường hợp, do đó, không có ý nghĩa khi đưa chúng vào khi sắp xếp một phiên bản.
Giải pháp đầu tiên là làm cho các thành viên đó không tĩnh. Hoặc, nếu những thành viên đó giống nhau trong lớp ban đầu và lớp đích (cùng một lớp, nhưng có thể là môi trường thời gian chạy khác nhau), thì đừng tuần tự hóa chúng.
Tôi có một vài suy nghĩ về cách người dùng có thể gửi qua các thành viên tĩnh, nhưng trước tiên tôi cần xem trường hợp sử dụng, như trong mọi trường hợp có nghĩa là cập nhật lớp đích và tôi không tìm thấy lý do chính đáng vì thế.
giả sử tôi muốn đếm số lượng cá thể của một lớp như Xe hơi. và tôi không sử dụng cơ sở dữ liệu .so trong trường hợp đó sau khi tắt ứng dụng, tôi cần phải lưu trữ thông tin này với các thông tin khác. –
Bạn có cần lưu số đó trực tiếp không? Nếu bạn cập nhật số khi bạn deserialize mỗi chiếc xe (bằng cách ghi đè readObject) nó sẽ phản ánh chính xác numbr của chiếc xe trong serialization. –
Biến tĩnh được chia sẻ giữa tất cả các cá thể của đối tượng của lớp (bộ nhớ dùng chung). Nếu bạn cần lưu một cái gì đó tĩnh, giống như cho phép bạn có một giá trị khác nhau và thỉnh thoảng bạn thay đổi giá trị tĩnh của kiểu enum đó, việc thay đổi giá trị đã lưu có thể đơn giản như tất cả các lớp đã thiết lập một biến cục bộ loại đó.Hoặc bạn có thể tiến thêm một bước nữa, và có một nhóm các lớp mở rộng Dù là gì, và bất cứ thứ gì có thể chỉ chia sẻ một biến cục bộ cho tất cả các con của nó. Khi bạn deserialize bạn có thể tải lại các giá trị tĩnh của bạn trở lại như thế nào. –
Thành viên tĩnh thuộc về lớp học, không phải cho các đối tượng riêng lẻ.
Bạn nên xem xét lại cấu trúc dữ liệu của mình.
Bạn có thể kiểm soát bằng cách thực hiện tuần tự:
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
Có một mô tả đầy đủ của serialization http://java.sun.com/developer/technicalArticles/Programming/serialization/.
Như các câu trả lời khác đã nói, nó không thực sự có ý nghĩa để sắp xếp các số liệu thống kê vì nó là đối tượng không phải lớp bạn đang sắp xếp và cần phải làm như vậy có mùi như bạn đã có các vấn đề khác với mã của bạn.
Bạn có thể kiểm soát tuần tự hóa, nhưng không có nơi nào hợp lý để đặt dữ liệu tĩnh bởi vì nó không có ý nghĩa gì trong ngữ cảnh. –
Vì chúng ta không biết bối cảnh, chúng ta không thể nói nó có ý nghĩa hay không. Ví dụ, sau khi sử dụng serialization mặc định, nó có thể có ý nghĩa để thêm thành viên tĩnh vào luồng. Tại deserialization, người ta có thể thiết lập các thành viên tĩnh nếu nó là null, nếu không loại bỏ các đối tượng serialized. – erickson
Tom, bạn đang lạm dụng "bằng chứng lặp lại", phải không? ;) –
Câu trả lời và nhận xét hay - đừng làm điều đó. Nhưng bằng cách nào?
Rất có thể bạn nên tắt một đối tượng để giữ tất cả "Statics" của mình. Đối tượng đó có lẽ nên có bất kỳ phương thức tĩnh nào từ lớp của bạn.
Mỗi trường hợp lớp học của bạn có thể tổ chức lớp học khác này - hoặc nếu bạn thực sự có để bạn có thể làm cho nó thành một singleton mà bất kỳ thành viên nào cũng có thể truy cập.
Sau khi bạn thực hiện công cụ này, bạn sẽ thấy rằng nó phải được thực hiện theo cách này. Bạn thậm chí có thể thấy rằng một số hạn chế thiết kế trước đó của bạn đã làm phiền bạn ở cấp độ subconsicionce đã biến mất.
Có thể bạn sẽ thấy rằng giải pháp này cũng giải quyết được các vấn đề khác về Serialization mà bạn chưa từng nhận thấy.
Mọi người, tĩnh không có nghĩa là IMMUTABLE. Ví dụ, tôi có thể muốn tuần tự hóa toàn bộ trạng thái tính toán (có, bao gồm các trường tĩnh - bộ đếm, vv) để tiếp tục sau, sau khi JVM và/hoặc máy tính chủ khởi động lại.
Câu trả lời đúng cho điều đó, như đã nói, là sử dụng giao diện Externalizable, chứ không phải Serializable. Sau đó, bạn có quyền kiểm soát hoàn toàn về những gì và cách bạn ngoại giao.
Nếu trạng thái của tính toán không được nhúng trong đối tượng bạn đang tuần tự hóa thì bạn không nên lưu trữ nó như một phần của việc tuần tự hóa đối tượng đó. – DJClayworth
Biến đổi tĩnh thường có nghĩa là bị hỏng. –
Hãy suy nghĩ lại. Ví dụ về các thuật toán di truyền đa luồng? Bộ nhớ chia sẻ (tĩnh) được sử dụng để giữ sổ đăng ký các biến thể được đánh giá. Làm cho nó một singleton? Có thể, nhưng nó có những hạn chế riêng. –
Có, chúng tôi có thể tuần tự hóa các biến tĩnh. Nhưng chúng tôi có thể viết riêng của chúng tôi writeObject()
và readObject()
. Tôi nghĩ rằng điều này có thể giải quyết vấn đề.
Để có thực hiện nhỏ gọn, thực hiện readObject & writeObject trong cuộc gọi lớp học của bạn defaultReadObject & phương pháp defaultWriteObject trong các phương pháp đó mà xử lý tuần tự bình thường và sau đó tiến hành tuần tự & de-serializing bất cứ lĩnh vực bổ sung mà bạn cần.
Kính trọng, GK
Đây là tuần tự cho trường tĩnh: newBookingNumber.
class Booking implements Serializable
{
/**
* Generated serial version ID.
*/
private static final long serialVersionUID = 5316748056989930874L;
// To hold new booking number.
private static int newBookingNumber = 0;
// The booking number.
private int bookingNumber;
/*
* Default serializable fields of a class are defined to be
* the non-transient and non-static fields. So, we have to
* write and read the static field separately.
*/
private void writeObject(ObjectOutputStream oos)
throws IOException
{
oos.defaultWriteObject();
oos.writeObject(new Integer(newBookingNumber));
}
private void readObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException
{
ois.defaultReadObject();
newBookingNumber = (Integer)ois.readObject();
}
}
Bạn có thể thực hiện việc này mà không phải cập nhật lớp học theo cách thủ công mỗi lần bạn chỉ cần thay đổi trường. Bạn có thể muốn thực hiện việc này nếu bạn muốn có các thành viên tĩnh dễ truy cập vào cài đặt trong một ứng dụng, nhưng cũng muốn lưu các cài đặt đó. Trong trường hợp này, bạn cũng sẽ muốn có tùy chọn để áp dụng chúng lúc đầu, không tải theo mặc định vì các giải pháp khác ở đây cần thiết, vì chúng là tĩnh. Điều này cho phép khôi phục cài đặt vì lý do hiển nhiên.
Về cơ bản, sử dụng các phương thức trường để nhận tất cả các thành viên trong lớp, sau đó ánh xạ tên đầy đủ của các trường này vào nội dung. Tên đầy đủ là bắt buộc vì Field không được tự tuần tự hóa. Sắp xếp lại bản đồ này và phục hồi nó để nhận các cài đặt đã lưu.
Phần thứ hai của câu đố là loại áp dụng() của hàm. Điều này đi qua việc lập bản đồ, và áp dụng những gì nó có thể cho lớp tĩnh.
Bạn cũng phải đảm bảo rằng nội dung của các thành viên tĩnh được tự tuần tự.
Như hy vọng có thể thấy từ lớp ví dụ này, các thành viên tĩnh có thể dễ dàng được lưu và trả về. Tôi sẽ để nó cho người triển khai lo lắng về UID của các lớp, các biện pháp bảo vệ, vv isSameAs() được sử dụng để kiểm thử đơn vị. AppSettings là lớp chứa tất cả các trường tĩnh mà bạn muốn tuần tự hóa.
public class AppSettingsReflectorSaver implements Serializable {
HashMap<String, Object> genericNamesAndContents = new HashMap<String, Object>();
private AppSettingsReflectorSaver() {
}
static AppSettingsReflectorSaver createAppSettingsSaver() {
AppSettingsReflectorSaver ret = new AppSettingsReflectorSaver();
ret.copyAppSettings();
return ret;
}
private void copyAppSettings() {
Field[] fields = AppSettings.class.getFields();
for (Field field : fields) {
mapContentsForSerialization(field);
}
}
private void mapContentsForSerialization(Field field) {
try {
Object fieldContents = field.get(AppSettings.class);
genericNamesAndContents.put(field.toGenericString(), fieldContents);
} catch (IllegalArgumentException ex) {
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex);
}
}
boolean isSameAs(AppSettingsReflectorSaver now) {
for(String thisKey : genericNamesAndContents.keySet()){
boolean otherHasThisKey = now.genericNamesAndContents.containsKey(thisKey);
Object thisObject = genericNamesAndContents.get(thisKey);
Object otherObject = now.genericNamesAndContents.get(thisKey);
boolean otherHasThisValue = thisObject.equals(otherObject);
if (!otherHasThisKey || !otherHasThisValue){
return false;
}
}
return true;
}
void applySavedSettingsToStatic() {
Field[] fields = AppSettings.class.getFields();
for (Field field : fields) {
if (!genericNamesAndContents.containsKey(field.toGenericString())){
continue;
}
Object content = genericNamesAndContents.get(field.toGenericString());
try {
field.set(AppSettings.class, content);
} catch (IllegalArgumentException ex) {
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
này được bài viết đầu tiên của tôi - đi dễ dàng trên tôi: P ~
- 1. Tuần tự hóa một lớp tĩnh?
- 2. khởi In-lớp của các thành viên dữ liệu tĩnh
- 3. Làm thế nào để bạn 'de-serialize' một lớp dẫn xuất từ dữ liệu tuần tự?
- 4. Các phương thức cũng được tuần tự hóa cùng với các thành viên dữ liệu trong .NET?
- 5. Làm thế nào để bỏ qua thành viên lớp học Sự kiện để tuần tự hóa nhị phân?
- 6. Tĩnh khẳng định để kiểm tra các thành viên dữ liệu lớp const tĩnh?
- 7. Các thành viên lớp tĩnh python
- 8. Làm thế nào để tuần tự hóa một gói?
- 9. Làm thế nào để tuần tự hóa/deserialize một hashmap?
- 10. Các vấn đề với các lớp bên trong không tĩnh và tuần tự hóa trong Java
- 11. Tuần tự hóa Java với khởi tạo tĩnh
- 12. Khởi tạo các thành viên tĩnh của một lớp templated
- 13. Làm thế nào tôi có thể tìm ra serialVersionUID của một đối tượng Java được tuần tự hóa?
- 14. Làm thế nào để tuần tự hóa các lớp mẫu có nguồn gốc với Boost.serialize?
- 15. DataContractSerializer: Cách tuần tự hóa các lớp/thành viên mà không có thuộc tính DataContract/DataMember
- 16. Các thành viên tĩnh của một lớp thể hiện
- 17. Java "tuần tự hóa phương thức" của lớp ẩn danh
- 18. Làm thế nào để tuần tự hóa/deserialize các lớp đơn giản thành XML và quay lại
- 19. Làm thế nào để truy cập các thành viên tĩnh trong một mẫu Velocity?
- 20. Làm cách nào để phân tích cú pháp một cơ sở dữ liệu tuần tự hóa PHP trong Java?
- 21. Làm cách nào để tạo một trường không thể tuần tự hóa được trong java?
- 22. Ngăn chặn việc tuần tự hóa các thành viên null trong DataContractSerializer
- 23. Làm thế nào để tuần tự hóa một DataTable thành một chuỗi?
- 24. Làm thế nào để cấu trúc lại một lớp được tuần tự hóa trong .NET?
- 25. Làm thế nào để tuần tự hóa ByteBuffer
- 26. Tuần tự hóa lớp ẩn danh trong Java
- 27. Làm thế nào để tuần tự hóa các đối tượng db.Model thành json?
- 28. Làm cách nào để truy cập một thành viên tĩnh công khai của một lớp Java từ ColdFusion?
- 29. Làm cách nào để tuần tự hóa một đối tượng thành một XDocument?
- 30. Làm thế nào để tuần tự hóa một đối tượng JavaScript chung thành XML
Dừng sử dụng các thành viên tĩnh cho dữ liệu đó phải được tuần tự? – krosenvold
Phụ lục: ngừng sử dụng thành viên tĩnh để giữ trạng thái có thể thay đổi. – Juliet
+1, nếu bạn tuần tự hóa, không sử dụng các thành viên tĩnh – marcgg