关于Scala中结构类型成员的反射访问的警告

时间:2014-11-06 19:31:45

标签: scala

这个警告意味着什么:

  

应该启用结构类型成员方法getMap的反射访问

警告包含对scala文档的引用,但我不明白我的代码与解释的关系。 (特别是解释提到了反思......我的代码如何使用反射?)

我有这个:(Scala 2.11.2)

object getMap {
    implicit def fromOptionToConvertedVal[T](o:Option[T]) = new {
        def getMap[R] (doWithSomeVal:(T) => R) = new {
            def orElse(handleNone: => R) = o match {
                case Some(value) => doWithSomeVal(value)
                case None => handleNone
            }
        }
    }   
}

import getMap._
val i:Option[Int] = Some(5)
val x = i getMap (_*2) orElse 1

这会在下面生成警告:

[warn] /Users/Greg/git/Favorites-Demo/src/main/scala/com/rs/server/ThriftServer.scala:34: reflective access of structural type member method getMap should be enabled
[warn] by making the implicit value scala.language.reflectiveCalls visible.
[warn] This can be achieved by adding the import clause 'import scala.language.reflectiveCalls'
[warn] or by setting the compiler option -language:reflectiveCalls.
[warn] See the Scala docs for value scala.language.reflectiveCalls for a discussion
[warn] why the feature should be explicitly enabled.
[warn] val x = i getMap (_*2) orElse 1
[warn]           ^
[warn] /Users/Greg/git/Favorites-Demo/src/main/scala/com/rs/server/ThriftServer.scala:34: reflective access of structural type member method orElse should be enabled
[warn] by making the implicit value scala.language.reflectiveCalls visible.
[warn] val x = i getMap (_*2) orElse 1
[warn]                        ^

1 个答案:

答案 0 :(得分:19)

我认为发生的事情是new { ... }对象是结构类型的,需要反思才能实现。

潜在的原因是Scala结构类型允许对象被视为根据它们实际具有的方法(如鸭子类型)而被视为多种类型的实例。 JVM只允许一种类型,因此不属于对象底层类型的方法必须通过普通虚方法调用之外的其他方式访问。在这种情况下使用的机制是反射。

当scala编译器看到对在结构类型对象上调用的方法的调用时,它(以某些优化为模)转换方法调用,如:

a.f(b, c)

a.getClass
    .getMethod("f", Array(classOf[B], classOf[C]))
    .invoke(a, Array(b, c))

取自the place where the technique was described的示例。

Scala团队决定对每个人都不会使用的高级功能实施选择加入政策。 reflectiveCalls

中记录了{{1}}恰好是其中之一