Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Scala反射:为什么getMethods可以返回val成员?_Java_Scala_Reflection - Fatal编程技术网

Java Scala反射:为什么getMethods可以返回val成员?

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 =

在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 =
      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
s
val
s是Scala构造,而不是Java构造。因此,Java反射不能返回关于
val
的任何信息,因为Java中没有
val
这样的东西。在Java中,与Scala
val
最接近的是getter方法,这正是Scala
val
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()方法