日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

scala反射详解

發布時間:2024/3/13 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 scala反射详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

Scala 的反射分為兩個范疇:
運行時反射:通常意義上的反射
編譯時反射:宏,或者元編程

這兩者之間的區別在于Environment, 而Environment又是由universe決定的. 反射的另一個重要的部分就是一個實體集合,而這個實體集合被稱為mirror,有了這個實體集合我們就可以實現對需要反射的類進行對應的操作,如屬性的獲取,屬性值得設置,以及對反射類方法的調用(其實就是成員函數的入口地址, 但請注意, 這只是個地址)!

可能有點繞, 說的直白點就是要操作類方法或者屬性就需要獲得指定的mirror,而mirror又是從Environment中得來的,而Environment又是Universes中引入的,而Universes根據運行時和編譯時又可以分為兩個領域的.

Universes

Universes有兩類,運行時和編譯時。提供了反射時要用的主要概念。such as Types, Trees, and Annotations。

  • scala.reflect.runtime.universe for runtime reflection
  • scala.reflect.macros.Universe for compile-time reflection.

Environment

Environment就是運行時和編譯時兩種環境

Mirrors

鏡像層級:

  • ClassLoaderMirror
  • ClassMirror ( => 類)
      • MethodMirror ( 只有構造函數)
  • InstanceMirror ( => 實例)
      • MethodMirror(方法)
      • FieldMirror(屬性)
  • ModuleMirror ( => Object)
      • instance: Any (單例類)

鏡像使用

Mirrors 提供了反射時要操作的實體(內存中的實體)。
mirror分兩大類:
“Classloader” mirrors : 通過staticClass/staticModule/staticPackage方法把變量轉為符號。
“Invoker” mirrors : 用于產生方法調用。是由 classloader mirror創建。包括:InstanceMirror,
MethodMirror,FieldMirror,ClassMirror 和 ModuleMirror。

Classloader入口
  • 鏡像的入口通過runtimeMirror()獲得。runtimeMirror 的返回值就是一個 classloader mirror。它是一個ReflectiveMirror。可以通過名字加載符號。
  • scala> import scala.reflect.runtime.universe._ import scala.reflect.runtime.universe._scala> val mirror = runtimeMirror(getClass.getClassLoader) val mirror: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@fb9c7aa of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [(memory)] and parent being scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@a5d23c9 of type class scala.reflect.internal.util.ScalaClassLoader$URLClassLoader with classpath [file:/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/jre/lib/resources.jar,file:/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/jre/lib/rt.jar,file:/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/jre/lib/jsse.jar,file:/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/jre/lib/jce.jar,file:/Library/Java/JavaVir...
    生成 invoker類型

    通過鏡像入口mirror (ReflectiveMirror) 來生成 invoker類型的實例。如 InstanceMirror

    case class Fruits(id: Int, name: String) {def func(): Unit = {println("func")}}scala> val fruits = Fruits(2, "banana") val fruits: Fruits = Fruits(2,banana)scala> val instanceMirror = mirror.reflect(fruits) val instanceMirror: reflect.runtime.universe.InstanceMirror = instance mirror for Fruits(2,banana)
    通過反射獲取實例的方法和屬性

    屬性和方法的反射要先獲得符號,再反射。屬性和方法都可以看成是符號(symbol) 通過下面的方法獲取:
    獲取屬性符號:

    scala> val field = typeOf[Fruits].decl(TermName("name")).asTerm val field: reflect.runtime.universe.TermSymbol = value namescala> val fieldMirror = instanceMirror.reflectField(field) val fieldMirror: reflect.runtime.universe.FieldMirror = field mirror for private[this] val name: String (bound to Fruits(2,banana))scala> fieldMirror.get val res3: Any = bananascala> fieldMirror.set("apple")scala> fieldMirror.get val res6: Any = apple

    獲取方法符號:

    // 方法符號 scala> val method = typeOf[Fruits].decl(TermName("func")).asMethod val method: reflect.runtime.universe.MethodSymbol = method func// 方法鏡像 scala> val methodMirror = instanceMirror.reflectMethod(method) val methodMirror: reflect.runtime.universe.MethodMirror = method mirror for def func(): Unit (bound to Fruits(2,apple))// 調用方法 scala> methodMirror() func val res7: Any = ()
    通過反射獲取構造函數

    獲取構造函數(通過ClassMirror),內部類的構造函數通過InstanceMirror獲得:

    scala> val clazz = typeOf[Fruits].typeSymbol.asClass clazz: reflect.runtime.universe.ClassSymbol = class Fruitsscala> val classMirror = mirror.reflectClass(clazz)classMirror: reflect.runtime.universe.ClassMirror = class mirror for Fruits (bound to null)scala> val constructMethod = typeOf[Fruits].decl(termNames.CONSTRUCTOR).asMethodconstructMethod: reflect.runtime.universe.MethodSymbol = constructor Fruitsscala> val methodMirror = classMirror.reflectConstructor(constructMethod)methodMirror: reflect.runtime.universe.MethodMirror = constructor mirror for def <init>(id: Int,name: String): Fruits (bound to null)scala> methodMirror(2, "banana") res2: Any = Fruits(2,banana)
    通過反射獲取單例對象

    ModuleMirror可以用來訪問object,內部object通過InstanceMirror獲得:

    import scala.reflect.runtime.universe._ val mirror = runtimeMirror(getClass.getClassLoader)object C { def x = 2 }scala> val module = typeOf[C.type].termSymbol.asModulemodule: reflect.runtime.universe.ModuleSymbol = object Cscala> val moduleMirror = mirror.reflectModule(module)moduleMirror: reflect.runtime.universe.ModuleMirror = module mirror for C (bound to null)scala> val instance = moduleMirror.instance // 生成anyinstance: Any = C$@5cb3bd9bscala> println(instance.asInstanceOf[C.type].x) // 2 2

    總結

    以上是生活随笔為你收集整理的scala反射详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。