我无法理解为什么在 2.11.1 中使用 scala 的运行时反射会给出看似不一致的结果。
我正在尝试检查 java 对象中包含的字段的类型,如下所示:
import java.util.List;
import java.util.ArrayList;
public class Example {
private List<Integer> listOfInts;
public Example () {
listOfInts = new ArrayList<Integer>();
}
}
现在假设我有一个 scala 程序,它尝试推理“Example:”内字段的类型
import java.lang.Class
import java.lang.reflect.Field
import java.util.List
import scala.reflect.runtime.{ universe => ru }
object Inspect extends scala.App {
val example = new Example
val cls = example.getClass
val listfield = cls.getDeclaredField("listOfInts")
println(isListType(listfield)) // prints false
println(isListType(listfield)) // prints true, as do all subsequent calls
def isListType (field: Field): Boolean = {
/*
A function that returns whether the type of the field is a list.
Based on examples at http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html
*/
val fieldcls = field.getType
val mirror: ru.Mirror = ru.runtimeMirror(getClass.getClassLoader)
val fieldsym: ru.ClassSymbol = mirror.classSymbol(fieldcls)
val fieldtype: ru.Type = fieldsym.toType
(fieldtype <:< ru.typeOf[List[_]])
}
}
在此特定代码片段中,第一次调用 isListType 返回 false,第二次调用返回 true。如果我将类型运算符从<:<
to =:=
,第一个调用返回 true,第二个调用返回 false。
我在较大的代码体中有一个类似的函数,并且发现即使该函数是静态对象的一部分,也会发生这种行为。使用非参数化类时不会发生这种情况。虽然我希望函数是纯粹的,但事实显然并非如此。进一步的实验表明,某个地方保存着一些持久状态。如果我更换isListType
函数与直线代码,我得到这个:
...
val example = new Example
val cls = example.getClass
val listfield = cls.getDeclaredField("listOfInts")
val fieldcls = listfield.getType
val mirror: ru.Mirror = ru.runtimeMirror(getClass.getClassLoader)
val fieldsym: ru.ClassSymbol = mirror.classSymbol(fieldcls)
val fieldtype: ru.Type = fieldsym.toType
println(fieldtype <:< ru.typeOf[List[_]]) // prints false
println(fieldtype <:< ru.typeOf[List[_]]) // prints false
但如果我在之后重新分配给字段类型<:<
运营商,我得到这个:
// replace as under the fieldsym assignment
var fieldtype: ru.Type = fieldsym.toType
println(fieldtype <:< ru.typeOf[List[_]]) // prints false
fieldtype = fieldsym.toType
println(fieldtype <:< ru.typeOf[List[_]]) // prints true
在重新分配给字段类型之前<:<
运算符给出:
// replace as under the fieldsym assignment
var fieldtype: ru.Type = fieldsym.toType
fieldtype = fieldsym.toType
println(fieldtype <:< ru.typeOf[List[_]]) // prints false
println(fieldtype <:< ru.typeOf[List[_]]) // prints false
有谁明白我在这里做错了什么,或者至少有办法解决这个问题?