在Scala中,我有Abstract Class
:
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))
输出是:
7
1
令我困惑的是:为什么getMethods
可以返回val
成员?
你知道,在子课程中,我有六 val
和一个功能。
在Oracle doc中,
public Method [] getMethods() throws SecurityException返回一个包含反映其所有公共成员方法的Method对象的数组 此Class对象表示的类或接口,包括 类或接口声明的那些以及从中继承的那些 超类和超接口
答案 0 :(得分:2)
Java并不了解val
。 val
是Scala构造,而不是Java构造。因此,Java反射不能返回val
的任何内容,因为Java中没有val
这样的东西。 Java中Scala val
最接近的是一个getter方法,这正是Scala val
在Java端表示的方式,这正是您使用Java反射而不是斯卡拉反思。
如果您使用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)
答案 1 :(得分:1)
除了@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
}
在课程名称后面立即查看public int test();
方法。