我在尝试命令模式,它在维基百科中的一个用法是这样的:
网络
可以通过网络发送整个命令对象,以便在其他机器上执行,例如计算机游戏中的玩家动作。
我假设这里发送对象意味着在对象的字段中发送数据,对吧?而不是execute()
方法中的代码?
我正在通过序列化进行实验;发现了一种我无法解释的行为。这是程序:
public class Test {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("Commands"))) {
Command command = () -> {
System.out.println("MUHAHA!");
};
outputStream.writeObject(command);
}
try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("Commands"))) {
Command command = (Command) inputStream.readObject();
command.execute();
}
}
}
interface Command extends Serializable {
void execute();
}
在执行时,我得到字符串MUHAHA!
。因此,execute()
方法的实现被保存在文件中。然而,如果我注释掉第一个try{}
块&然后执行,它将失败。Commands
文件保留了上次执行的内容,但未能读取&作语法分析
我得到以下堆栈跟踪:
Exception in thread "main" java.io.IOException: unexpected exception type
at java.io.ObjectStreamClass.throwMiscException(Unknown Source)
at java.io.ObjectStreamClass.invokeReadResolve(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at random.Test.main(Test.java:18)
Caused by: java.lang.NoSuchMethodException: random.Test.$deserializeLambda$(java.lang.invoke.SerializedLambda)
at java.lang.Class.getDeclaredMethod(Unknown Source)
at java.lang.invoke.SerializedLambda$1.run(Unknown Source)
at java.lang.invoke.SerializedLambda$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.lang.invoke.SerializedLambda.readResolve(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
... 5 more
NoSuchMethodException
对我来说有些道理,但为什么它不是第一次出现呢?它是否将通过lambda创建的第一个类存储在某个缓存(或元空间)中?
最后,是否可以发送一个实现?我希望在另一端,execute
方法的代码将被写入一些动态创建的Command
实现中。
它没有将实现存储在文件中。为了说明这一点,请将代码分为两个类:一个序列化,另一个反序列化,和在不同的环境中执行它们,而这两个环境都没有另一个的.class文件。