为什么呢火花工作scala.beans.beanproperty不同(Why does scala.

2019-09-30 11:18发布

在一阶REPL下面的代码

import scala.beans.BeanProperty

class EmailAccount {
  @scala.beans.BeanProperty var accountName: String = null

  override def toString: String = {
    return s"acct ($accountName)"
  }
}
classOf[EmailAccount].getDeclaredConstructor()

结果是

res0: java.lang.reflect.Constructor[EmailAccount] = public EmailAccount()

然而,在火花的REPL我得到

java.lang.NoSuchMethodException: EmailAccount.<init>()
  at java.lang.Class.getConstructor0(Class.java:2810)
  at java.lang.Class.getDeclaredConstructor(Class.java:2053)
  ... 48 elided

是什么原因导致这种差异? 我怎样才能激发相匹配的火花shell的行为。

我公司推出的REPLs像这样:

/home/placey/Downloads/spark-2.0.0-bin-hadoop2.7/bin/spark-shell --master local --jars /home/placey/snakeyaml-1.17.jar

scala -classpath "/home/placey/snakeyaml-1.17.jar

斯卡拉版本火花:

Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_55)

斯卡拉:

Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_55).

Answer 1:

其实,这是不特定于scala.beans.BeanProperty甚至星火。 您可以通过运行它获得标准斯卡拉REPL相同的行为-Yrepl-class-based参数:

scala -Yrepl-class-based

现在,让我们试着定义一个简单的空类:

scala> class Foo()
defined class Foo

scala> classOf[Foo].getConstructors
res0: Array[java.lang.reflect.Constructor[_]] = Array(public Foo($iw))

scala> classOf[Foo].getFields
res1: Array[java.lang.reflect.Field] = Array(public final $iw Foo.$outer)

正如你所看到的,REPL通过添加额外的领域和参数构造函数修改对飞类。 为什么?

当你创建一个valvar在斯卡拉REPL,它被包裹在一个特殊的对象,因为有在斯卡拉“全局变量”没有这样的事。 见这个答案 。

通常情况下,这是一个对象,因此它在全球上市。 然而,随着-Yrepl-class-based的REPL使用,而不是一个全局对象类的实例。 此功能是通过星火开发商介绍,因为星火需要类可序列化,这样他们就可以被发送到远程工作人员(见本pull请求 )。

正因为如此,你在REPL定义任何类需要得到$iw实例。 否则,你将无法进入全球val S和var你在REPL定义秒。 此外,生成的类自动扩展Serializable

恐怕你不能做任何事情,以防止这一点spark-shell使得-Yrepl-class-based默认。 即使有禁用此行为的选项,你会碰到很多其他的问题,因为你的类将不再是可序列化,但星火需要序列化。



文章来源: Why does scala.beans.beanproperty work differently in spark