gpt4 book ai didi

class - 即使是 Scala 中简单的序列化示例也不起作用。为什么?

转载 作者:行者123 更新时间:2023-12-04 01:22:57 24 4
gpt4 key购买 nike

我正在尝试一个类的最简单的序列化示例:

@serializable class Person(age:Int) {}
val fred = new Person(45)
import java.io._
val out = new ObjectOutputStream(new FileOutputStream("test.obj"))
out.writeObject(fred)
out.close()

这会在我身上引发异常“java.io.NotSerializableException: Main$$anon$1$Person”。为什么?
有没有简单的序列化示例?
我也试过
@serializable class Person(nm:String) {
private val name:String=nm
}
val fred = new Person("Fred")
...

并试图删除 @serializable和其他一些排列。文件“test.obj”已创建,大小超过 2Kb,内容合理。

编辑:

重新读取“test.obj”(来自下面的第二个答案)导致

Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51). Type in expressions to have them evaluated. Type :help for more information.

scala> import java.io._ import java.io._

scala> val fis = new FileInputStream( "test.obj" ) fis: java.io.FileInputStream = java.io.FileInputStream@716ad1b3

scala> val oin = new ObjectInputStream( fis ) oin: java.io.ObjectInputStream = java.io.ObjectInputStream@1f927f0a

scala> val p= oin.readObject java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: Main$$anon$1 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1354) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) at .(:12) at .() at .(:7) at .() at $print() at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734) at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983) at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573) at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604) at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568) at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:756) at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:801) at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:713) at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:577) at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:584) at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:587) at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:878) at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:833) at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:833) at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135) at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:833) at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:83) at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96) at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105) at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) Caused by: java.io.NotSerializableException: Main$$anon$1 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347) at Main$$anon$1.(a.scala:11) at Main$.main(a.scala:1) at Main.main(a.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:71) at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31) at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:139) at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:71) at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:139) at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28) at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45) at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35) at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45) at scala.tools.nsc.ScriptRunner.scala$tools$nsc$ScriptRunner$$runCompiled(ScriptRunner.scala:171) at scala.tools.nsc.ScriptRunner$$anonfun$runScript$1.apply(ScriptRunner.scala:188) at scala.tools.nsc.ScriptRunner$$anonfun$runScript$1.apply(ScriptRunner.scala:188) at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply$mcZ$sp(ScriptRunner.scala:157) at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:131) at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:131) at scala.tools.nsc.util.package$.trackingThreads(package.scala:51) at scala.tools.nsc.util.package$.waitingForThreads(package.scala:35) at scala.tools.nsc.ScriptRunner.withCompiledScript(ScriptRunner.scala:130) at scala.tools.nsc.ScriptRunner.runScript(ScriptRunner.scala:188) at scala.tools.nsc.ScriptRunner.runScriptAndCatch(ScriptRunner.scala:201) at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:76) ... 3 more

最佳答案

请注意 @serializable scaladoc 告诉它自 2.9.0 以来已被弃用:

Deprecated (Since version 2.9.0) instead of @serializable class C, use class C extends Serializable



所以你只需要使用 Serializable特征:
class Person(val age: Int) extends Serializable

这对我有用(在 REPL 中输入 :paste 并粘贴这些行):
import java.io.{ObjectOutputStream, ObjectInputStream}
import java.io.{FileOutputStream, FileInputStream}

class Person(val age: Int) extends Serializable {
override def toString = s"Person($age)"
}

val os = new ObjectOutputStream(new FileOutputStream("/tmp/example.dat"))
os.writeObject(new Person(22))
os.close()

val is = new ObjectInputStream(new FileInputStream("/tmp/example.dat"))
val obj = is.readObject()
is.close()
obj

这是输出:
// Exiting paste mode, now interpreting.

import java.io.{ObjectOutputStream, ObjectInputStream}
import java.io.{FileOutputStream, FileInputStream}
defined class Person
os: java.io.ObjectOutputStream = java.io.ObjectOutputStream@5126abfd
is: java.io.ObjectInputStream = java.io.ObjectInputStream@41e598aa
obj: Object = Person(22)
res8: Object = Person(22)

所以,你可以看到,[反]序列化尝试是成功的。

编辑(关于从文件运行 Scala 脚本时为什么会得到 NotSerializableException)

我已将代码放入文件并尝试通过 scala test.scala 运行它并得到与您完全相同的错误。这是我对为什么会发生的猜测。

根据堆栈跟踪,一个奇怪的类 Main$$anon$1不可序列化。逻辑问题是:为什么它首先存在?我们正在尝试序列化 Person毕竟,不是什么奇怪的东西。

Scala 脚本的特殊之处在于它被隐式包装到一个名为 Main 的对象中。 .这由堆栈跟踪指示:
at Main$$anon$1.<init>(test.scala:9)
at Main$.main(test.scala:1)
at Main.main(test.scala)

这里的名字暗示 Main.main静态方法是程序入口点,该方法委托(delegate)给 Main$.main实例方法( object 的类以对象命名,但附加了 $)。这个实例方法反过来尝试创建一个类的实例 Main$$anon$1 .据我记得,匿名类就是这样命名的。

现在,让我们尝试找到确切的 Person类名(作为 Scala 脚本运行):
class Person(val age: Int) extends Serializable {
override def toString = s"Person($age)"
}

println(new Person(22).getClass)

这打印出我期待的东西:
class Main$$anon$1$Person

这意味着 Person不是顶级类;相反,它是在编译器生成的匿名类中定义的嵌套类!所以实际上我们有这样的东西:
object Main {
def main(args: Array[String]) {
new { // this is where Main$$anon$1 is generated, and the following code is its constructor body
class Person(val age: Int) extends Serializable { ... }
// all other definitions
}
}
}

但在 Scala 中,所有嵌套类在 Java 中都称为“嵌套非静态”(或“内部”)类。这意味着这些类总是包含对其封闭类实例的隐式引用。在这种情况下,封闭类是 Main$$anon$1 .因此,当 Java 序列化程序尝试序列化 Person ,它会传递遇到 Main$$anon$1 的实例并尝试序列化它,但因为它不是 Serializable ,过程失败。顺便说一句,序列化非静态内部类在 Java 世界中是一件臭名昭著的事情,众所周知会导致这样的问题。

至于为什么它在 REPL 中起作用,似乎在 REPL 中声明的类以某种方式最终不会成为内部类,因此它们没有任何隐式字段。因此,序列化对他们来说正常工作。

关于class - 即使是 Scala 中简单的序列化示例也不起作用。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23182577/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com