我将createSocket()测试用例中的方法重写为模拟Socket中的pas。完成此操作后,对象将不再可序列化。
createSocket()
这是不起作用的示例。
Foo.java
import java.io.Serializable; public class Foo implements Serializable { private static final long serialVersionUID = 3109852436898487119L; public void bar() { System.out.println("Foo"); } }
FooTest.java
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import junit.framework.TestCase; import org.junit.Test; public class FooTest extends TestCase { // this passes @Test public void testFooIsSerializable() throws IOException { Foo foo = new Foo(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(foo); } // this throws a java.io.NotSerializableException @Test public void testFooIsStillSerializableAfterBarIsOverridden() throws IOException { // Eclipse gives me the warning "The serializable class does not declare a static final serialVersionUID field of type long" // Adding it doesn't help Foo foo = new Foo() { @Override public void bar() { System.out.println("Bar"); } }; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(foo); } }
使用JUnit运行FooTest时的堆栈跟踪:
java.io.NotSerializableException: FooTest at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330) at FooTest.testFooIsStillSerializableAfterBarIsOverridden(FooTest.java:33) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at junit.framework.TestCase.runTest(TestCase.java:168) at junit.framework.TestCase.runBare(TestCase.java:134) at junit.framework.TestResult$1.protect(TestResult.java:110) at junit.framework.TestResult.runProtected(TestResult.java:128) at junit.framework.TestResult.run(TestResult.java:113) at junit.framework.TestCase.run(TestCase.java:124) at junit.framework.TestSuite.runTest(TestSuite.java:232) at junit.framework.TestSuite.run(TestSuite.java:227) at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
这是什么问题?我不得不承认,我并没有深入研究Java的Serializable接口,或多或少只是遵循了Eclipse的快速修复程序。
更具体地讲我的实现:
我有一个应该通过ObjectOutputStream发送其自身实例的类。
这是根本错误的方法吗?
问题是您有一个匿名内部类,根据定义,该内部类 包含(FooTest由 编译器生成的)对 创建它 的外部类( ) 实例的引用 。由于默认情况下序列化包括对象的所有成员,因此运行时FooTest也会尝试序列化对象-并且 这 是不可序列化的(因为它本来就不是)。错误消息证明了这一点:
FooTest
java.io.NotSerializableException: FooTest
因此,如果您将匿名类转换为显式static内部类,则该问题将消失。
static