2010-10-01 36 views
61

Tôi đang thực hiện một lớp để được Serializable (vì vậy nó là một đối tượng giá trị để sử dụng w/RMI). Nhưng tôi cần phải kiểm tra nó. Có cách nào để làm điều này một cách dễ dàng?làm thế nào để kiểm tra trong Java rằng một lớp thực hiện đúng Serializable (không chỉ là một thể hiện của Serializable)

làm rõ: Tôi đang triển khai lớp học, do đó, nó tầm thường để gắn Serializable trong định nghĩa lớp học. Tôi cần phải tự serialize/deserialize nó để xem nếu nó hoạt động.

Tôi tìm thấy điều này C# question, có câu trả lời tương tự cho Java không?

+0

Bạn đang cố gắng kiểm tra xem đối tượng g ets được tuần tự hóa và deserialized đúng cách? –

+0

có. (.........) –

Trả lời

100

Cách dễ dàng là kiểm tra đối tượng là một thể hiện của java.io.Serializable hoặc java.io.Externalizable, nhưng điều đó không thực sự chứng minh rằng đối tượng thực sự có thể tuần tự hóa được.

Cách duy nhất để chắc chắn là thử thực tế. Bài kiểm tra đơn giản nhất là:

new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(myObject); 

và kiểm tra xem nó không ném ngoại lệ.

Apache Commons Lang cung cấp một phiên bản khá ngắn gọn hơn:

SerializationUtils.serialize(myObject); 

và một lần nữa, kiểm tra các ngoại lệ.

Bạn có thể rigourous hơn vẫn còn, và kiểm tra xem nó deserializes trở lại vào một cái gì đó tương đương với bản gốc:

Serializable original = ... 
Serializable copy = SerializationUtils.clone(original); 
assertEquals(original, copy); 

và vân vân.

+0

cool, cảm ơn, đó là phần giới thiệu mà tôi cần. –

+0

Chỉ trong trường hợp ai đó tò mò hoặc không muốn bao gồm các thư viện Apache Commons, Spring cũng có SerializationUtils với các phương thức 'serialize' và' deserialize'. Xem [SerializationUtils] (http://docs.spring.io/spring/docs/4.1.0.BUILD-SNAPSHOT/javadoc-api/org/springframework/util/SerializationUtils.html) –

+0

Câu trả lời của bạn đã giúp tôi, nhưng 'deserialize() 'và' clone() 'trả về' Đối tượng', không phải 'Nối tiếp'. – NeplatnyUdaj

2

Câu trả lời ngắn gọn là, bạn có thể đưa ra một số đối tượng thí sinh và thực sự cố gắng để serialize họ sử dụng cơ chế bạn chọn. Các thử nghiệm ở đây là không có lỗi gặp phải trong marshalling/unmarshalling, và rằng kết quả "rehydrated" đối tượng bằng với bản gốc. Ngoài ra, nếu bạn không có bất kỳ đối tượng ứng cử viên nào, bạn có thể thực hiện phép thử dựa trên phản chiếu để quan sát các trường (không tĩnh, không tạm thời) trong lớp của bạn để đảm bảo rằng chúng cũng có thể được tuần tự hóa. Nói từ kinh nghiệm, điều này đáng ngạc nhiên phức tạp một cách đáng ngạc nhiên một cách nhanh chóng, nhưng nó có thể được thực hiện đến một mức độ hợp lý.

Nhược điểm của phương pháp thứ hai này là nếu một trường là ví dụ: List<String>, sau đó bạn có thể thất bại trong lớp không có trường tuần tự đúng, hoặc chỉ đơn giản giả định rằng việc triển khai danh sách có thể tuần tự sẽ được sử dụng. Không phải là hoàn hảo.(Tâm trí bạn, vấn đề thứ hai tồn tại cho các ví dụ quá, nếu mỗi ví dụ được sử dụng trong thử nghiệm sử dụng danh sách serializable, không có gì để ngăn chặn một phiên bản không serializable đang được sử dụng bởi một số mã khác trong thực tế).

3

Mã này nên làm điều đó ... phương pháp

import java.io.ByteArrayOutputStream; 
import java.io.Externalizable; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.io.OutputStream; 
import java.io.Serializable; 

public class Main 
{ 
    public static void main(String[] args) 
    { 
     System.out.println(isSerializable("Hello")); 
     System.out.println(isSerializable(new Main())); 
    } 

    public static boolean isSerializable(final Object o) 
    { 
     final boolean retVal; 

     if(implementsInterface(o)) 
     { 
      retVal = attemptToSerialize(o); 
     } 
     else 
     { 
      retVal = false; 
     } 

     return (retVal); 
    } 

    private static boolean implementsInterface(final Object o) 
    { 
     final boolean retVal; 

     retVal = ((o instanceof Serializable) || (o instanceof Externalizable)); 

     return (retVal); 
    } 

    private static boolean attemptToSerialize(final Object o) 
    { 
     final OutputStream sink; 
     ObjectOutputStream stream; 

     stream = null; 

     try 
     { 
      sink = new ByteArrayOutputStream(); 
      stream = new ObjectOutputStream(sink); 
      stream.writeObject(o); 
      // could also re-serilalize at this point too 
     } 
     catch(final IOException ex) 
     { 
      return (false); 
     } 
     finally 
     { 
      if(stream != null) 
      { 
       try 
       { 
        stream.close(); 
       } 
       catch(final IOException ex) 
       { 
        // should not be able to happen 
       } 
      } 
     } 

     return (true); 
    } 
} 
+0

'instanceof Externalizable' ngụ ý' instanceof Serializable'. Bạn không cần phải kiểm tra cả hai. – EJP

22

tiện ích dựa trên câu trả lời của skaffman:

private static <T extends Serializable> byte[] pickle(T obj) 
     throws IOException 
{ 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(baos); 
    oos.writeObject(obj); 
    oos.close(); 
    return baos.toByteArray(); 
} 

private static <T extends Serializable> T unpickle(byte[] b, Class<T> cl) 
     throws IOException, ClassNotFoundException 
{ 
    ByteArrayInputStream bais = new ByteArrayInputStream(b); 
    ObjectInputStream ois = new ObjectInputStream(bais); 
    Object o = ois.readObject(); 
    return cl.cast(o); 
} 
+0

++ cảm ơn bạn và nghệ sĩ! Tôi đã tìm kiếm một cái gì đó như thế này để thêm vào một khai thác thử nghiệm để ngăn chặn các nhà phát triển từ viết mã đó là không Serializable và giết chết các ứng dụng của chúng tôi một khi họ đạt đến máy chủ cụm của chúng tôi. Một cuộc sống tiết kiệm! Cảm ơn các bạn! –

+0

Tìm hiểu thêm về thuật ngữ "tẩy" ở đây: https://docs.python.org/2/library/pickle.html – span

1

này chỉ hoạt động cho các đối tượng đầy đủ dân cư, nếu bạn yêu cầu bất kỳ đối tượng bao gồm trong của bạn đối tượng cấp cao nhất cũng có thể tuần tự hóa được sau đó chúng không thể rỗng để thử nghiệm này hợp lệ khi tuần tự hóa/deserialization bỏ qua các đối tượng null

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