我正在尝试类的最简单的序列化示例:
@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”返回(来自下面的第二个答案)的原因
欢迎使用Scala版本2.10.3(JavaHotSpot(TM)64位服务器VM,Java1.7.0_51)。键入表达式以计算它们。类型:帮助获取更多信息。
斯卡拉
斯卡拉
斯卡拉
斯卡拉
class-Person(age:Int){}
相当于Java代码:
class Person{
Person(Int age){}
}
这可能不是你想要的。请注意,age
参数被简单地丢弃,Person
没有成员字段。
你想要:
>
@serializable class-Person(val-age:Int)
你可以省略结尾处的空花括号。事实上,这是受到鼓励的。
您可以使用可序列化特性:
使用具有可序列化特性的Java序列化的简单序列化示例:
case class Person(age: Int) extends Serializable
用法:
序列化,写入对象
val fos = new FileOutputStream( "person.serializedObject" )
val o = new ObjectOutputStream( fos )
o writeObject Person(31)
反序列化,读取对象
val fis = new FileInputStream( "person.serializedObject" )
val oin = new ObjectInputStream( fis )
val p= oin.readObject
从而产生以下输出
fis: java.io.FileInputStream = java.io.FileInputStream@43a2bc95
oin: java.io.ObjectInputStream = java.io.ObjectInputStream@710afce3
p: Object = Person(31)
正如您所见,反序列化无法推断对象类型本身,这是一个明显的缺点。
用Scala酸洗序列化
https://github.com/scala/pickling或者从Scala 2.11开始的部分标准发行版
在示例代码中,对象不会写入文件,而是使用JSON而不是字节码序列化,这避免了因不同Scala版本之间字节码不兼容而产生的某些问题。
import scala.pickling._
import json._
case class Person(age: Int)
val person = Person(31)
val pickledPerson = person.pickle
val unpickledPerson = pickledPerson.unpickle[Person]
请注意,@serializable
scaladoc告诉我们,它从2.9.0开始就被弃用了:
已弃用(自版本2.9.0起)而不是@serializable class C,请使用class C extends serializable
所以你只需要使用Serializable
trait:
class Person(val age: Int) extends Serializable
这对我有用(在REPL中键入:粘贴
,然后粘贴这些行):
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)
因此,您可以看到,[de]序列化尝试是成功的。
编辑(关于从文件运行Scala脚本时为什么会出现
NotSerializableException
)
我已经将代码放入一个文件中,并试图通过scala测试运行它。scala
并得到了与您完全相同的错误。以下是我对其原因的猜测。
根据堆栈跟踪,一个奇怪的类
Main$$anon$1
不可序列化。合乎逻辑的问题是:它为什么会存在?毕竟,我们试图序列化人
,而不是奇怪的东西。
Scala脚本的特殊之处在于,它隐式地封装在名为
Main
的对象中。这由堆栈跟踪指示:
at Main$$anon$1.<init>(test.scala:9)
at Main$.main(test.scala:1)
at Main.main(test.scala)
这里的名称表明
Main.main
静态方法是程序切入点,该方法委托给Main$. main
实例方法(对象
的类以对象命名,但使用$
附加)。此实例方法依次尝试创建类Main$anon1美元
的实例。在我的记忆中,匿名类就是这样命名的。
现在,让我们试着找到确切的
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 serializer尝试序列化Person
时,它会临时遇到Main$$anon$1
的一个实例,并尝试对其进行序列化,但由于它不可序列化
,因此该过程失败。顺便说一句,序列化非静态内部类在Java世界是一件臭名昭著的事情,众所周知,它会导致类似这样的问题。
至于它在REPL中工作的原因,似乎在REPL中声明的类在某种程度上不会最终成为内部类,因此它们没有任何隐式字段。因此,序列化通常适用于它们。
问题内容: 杰克逊(Jackson)做的事情确实很奇怪,我找不到任何解释。我正在执行多态序列化,当对象独立时它可以完美地工作。但是,如果将同一个对象放入列表中并对其进行序列化,则会删除类型信息。 它丢失类型信息的事实将导致人们怀疑类型擦除。但这是在列表 内容 的序列化过程中发生的。Jackson要做的只是检查要序列化的当前对象以确定其类型。 我使用杰克逊2.5.1创建了一个示例: 这是输出: 如您
我有一个从CSV文件读取的: 据我所知,是一个POJO: 我还有一个简单的课程: 但当我尝试使用它时,例如从测试中: 我得到以下错误: 我读过这些问题和答案,但运气不好: 任务不可序列化Flink 无法在scala中序列化任务 任务不可序列化:java。伊奥。仅在类而非对象上调用闭包外函数时NotSerializableException
问题内容: 为什么以下显示在Linux和Windows中有所不同? 在Windows中: ¿ 在Linux中: 一个 问题答案: System.out.println()以系统默认编码输出文本,但是控制台根据其自身的编码(或“代码页”)设置解释该输出。在Windows机器上,这两种编码似乎匹配,但是在Linux机器上,输出显然是以UTF-8格式输出的,而控制台将其解码为ISO-8859-1之类的单
我正在再次学习一些面向对象的概念,所以我编写了这个简单的代码,只是为了看看重写方法是如何工作的,令人惊讶的是,它不工作了。另外,忽略类名为HelloWorld的事实,它只是一个用于学习目的的文件。它已经改成了Filha。java btw 昨天,错误是线程“main”java中的异常。错误:公共静态void main(String[]args){line中未解决的编译问题,但我关闭了我的计算机,今天
我正试图编写代码,从一个Android应用程序发送一条短信,但当我试图发送短信时,它给我返回了错误: 我检查了,但我拥有清单中的权限,如下所示: null null 我在网上搜索了一下,但是所有的错误都是关于语法的,你能帮我一下吗?
问题内容: 我是Java的新手,正在尝试学习速记语句的概念。 我想出了下面的代码。但是,该代码将无法编译,并在(即?:)语句旁边显示错误。 有人可以告诉我为什么它不起作用吗? 对不起,如果我的问题对某些人听起来很愚蠢。我是Java新手。 在此先感谢您的帮助! 问题答案: 三元表达 是一个 表达式 ,而不是一个语句,因此不能在需要语句的地方使用。 您可以这样写: 因为这是一个声明。