Java Scala反射:为什么getMethods可以返回val成员?
在Scala中,我有一个Java Scala反射:为什么getMethods可以返回val成员?,java,scala,reflection,Java,Scala,Reflection,在Scala中,我有一个抽象类: abstract class AbstractSQLParser { def apply(input: String): Int = { println(reserveWords) return 1 } protected case class Keyword(str: String) // use Reflection here protected lazy val reserveWords: Int =
抽象类
:
abstract class AbstractSQLParser {
def apply(input: String): Int = {
println(reserveWords)
return 1
}
protected case class Keyword(str: String)
// use Reflection here
protected lazy val reserveWords: Int =
this.getClass
.getMethods
.filter(_.getReturnType == classOf[Keyword])
.length
}
另一个扩展了它:
class SqlParserDemo extends AbstractSQLParser{
def apply(input: String, onError: Boolean) : Int = {
apply(input)
}
protected val CREATE = Keyword("CREATE")
protected val TEMPORARY = Keyword("TEMPORARY")
protected val TABLE = Keyword("TABLE")
protected val IF = Keyword("IF")
protected val NOT = Keyword("NOT")
protected val EXISTS = Keyword("EXISTS")
def func1 = Keyword("HI")
}
但是当我打电话的时候
val sqlParser = new SqlParserDemo
print(sqlParser.apply("hello", false))
输出为:
七,
一,
让我困惑的是:为什么getMethods
可以返回val
成员
你看,在子类中,我有六个val,和一个one函数
在Oracle文档中
公共方法[]getMethods()
抛出SecurityException返回一个数组,该数组包含反映
此类对象表示的类或接口,包括
由类或接口声明的以及从
超类与超接口
Java不知道
val
sval
s是Scala构造,而不是Java构造。因此,Java反射不能返回关于val
的任何信息,因为Java中没有val
这样的东西。在Java中,与Scalaval
最接近的是getter方法,这正是Scalaval
s在Java端的表示方式,也是使用Java反射而不是Scala反射时得到的结果
如果使用Scala反射,将得到以下结果:
import scala.reflect.runtime.{universe => ru}
def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]
val theType = getTypeTag(sqlParser).tpe
theType.declarations
// => reflect.runtime.universe.MemberScope =
// SynchronizedOps(
// constructor SqlParserDemo,
// value CREATE,
// value CREATE,
// value TEMPORARY,
// value TEMPORARY,
// value TABLE,
// value TABLE,
// value IF,
// value IF,
// value NOT,
// value NOT,
// value EXISTS,
// value EXISTS,
// method func1)
除了@Jorg W Mittag答案。您可以编译Scala代码,然后使用Java反编译器分析生成的类。例如下面是带有唯一
val
的Scala类:
class Test {
val test = 5;
}
编译它,当反编译时,您会得到:
public class Test
{
private final int test = 5;
public int test() { return this.test; }
}
所以Java反射发现的是Scala编译器生成的合成方法,用于将val
添加到JVM中
或者,如果您喜欢检查字节码:
.../Workspace/Scala/TestVal>javap -c Test
Compiled from "Test.scala"
public class Test {
public int test();
Code:
0: aload_0
1: getfield #13 // Field test:I
4: ireturn
public Test();
Code:
0: aload_0
1: invokespecial #19// Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_5
6: putfield #13 // Field test:I
9: return
}
../Workspace/Scala/TestVal>javap-c测试
从“Test.scala”编译而来
公开课考试{
公共int测试();
代码:
0:aload_0
1:getfield#13//现场测试:I
4:我轮到你了
公开考试();
代码:
0:aload_0
1:invokespecial#19//方法java/lang/Object。“:()V
4:aload_0
5:iconst_5
6:putfield#13//现场测试:I
9:返回
}
请参阅,public int test()紧跟在类名之后的代码>方法