近期有需求,要根據解析字符串,根據字符串的內容去調用方法。
想到的基本就是使用反射。但是基本上能找到的資料,全沒有講scala的反射。只有零星點點的講解。
大部分都是用scala的語法寫java反射
最后翻了翻scala的官方文檔
發現還在實驗階段。
一不做二不休,索性兩種反射方式都來嘗試嘗試。
其實兩種方式實現起來,都差不多,scala的方式好處在於可以反射閉包。
不過這篇文章是講解的基礎的一些反射,后續補上閉包的反射等等。
以下只講解關鍵代碼,具體細節部分可以參閱官方文檔。http://docs.scala-lang.org/overviews/reflection/overview.html
主要實現:
反射調用 scala class 中的函數
反射調用 scala object 中的函數
java 實現反射:
java反射需要繼承序列化
extends Serializable
反射調用 scala class 中的函數
val clazz = Class.forName("com.testclass") //構造一個需要反射類的對象
clazz //使用該對象去獲取私有函數 .getDeclaredMethod(s"$函數名", classOf[String], classOf[String]) //並得到該函數入參的數據類型,如有多個入參,要聲明多個classOf
.invoke(clazz.newInstance(), 入參1, 入參2) //激活該函數,傳入入參
.asInstanceOf[String] //最后結果強轉下類型,scala默認是返回AnyRef類型
反射調用 scala object 中的函數
val clazz = Class.forName("com.testobject") clazz .getDeclaredMethod(s"$函數名", classOf[String], classOf[String]) .invoke(null, 入參1, 入參2) //相當於調用java的靜態成員,直接調用就行不需要再new加載
.asInstanceOf[String]
scala 實現反射:
scala反射需要引包
import scala.reflect.runtime.{universe => ru}
反射調用 scala class 中的函數
val classMirror = ru.runtimeMirror(getClass.getClassLoader) //獲取運行時類鏡像
val classTest = ClassMirror.reflect(new com.testclass) //獲取需要反射的類對象
val methods = ru.typeOf[com.testclass] //構造獲取方式的對象
val method = Methods.decl(ru.TermName(s"$函數名")).asMethod //獲取需要調用的函數
val result = classTest.reflectMethod(Method)(入參1, 入參2) //反射調用函數,並傳入入參
result.asInstanceOf[String] //返回的結果強轉下類型,scala默認是AnyRef類型
反射調用 scala object 中的函數
val classMirror = ru.runtimeMirror(getClass.getClassLoader) //獲取運行時類鏡像
val classTest = classMirror.staticModule("com.testobject") //獲取需要反射object
val methods = classMirror.reflectModule(classTest) //構造獲取方式的對象
val objMirror = classMirror.reflect(methods.instance) //反射結果賦予對象
val method = methods.symbol.typeSignature.member(ru.TermName(s"$函數名")).asMethod //反射調用函數
val result = objMirror.reflectMethod(method)(入參1, 入參2) //最后帶參數,執行這個反射調用的函數
result.asInstanceOf[String] //結果強轉下類型