Scala反射API

反射创建 Object单例

package demo

object A {
  val i = 1
}

通过 java 常规的方式是不行的

val clazz = Class.forName("demo.A")
val constructors: Array[Constructor[_]] = clazz.getConstructors
val declaredConstructors: Array[Constructor[_]] = clazz.getDeclaredConstructors
println(constructors.length)          // 0
println(declaredConstructors.length)  // 0

object编译后会生成下面两个类:A.class 和 A$.class,使用 jd-gui 反编译后是下面这样子:

package demo;

public final class A$
{
  public static final A$ MODULE$ = new A$();
}

package demo;

import scala.reflect.ScalaSignature;

@ScalaSignature(bytes = "\006\005M9Qa\001\003\t\002\0351Q!\003\003\t\002)AQ!E\001\005\
002I\t\021!\021\006\002\013\005!A-Z7p\007\001\001\"\001C\001\016\003\021\021\021!Q\n\003\
003-\001\"\001D\b\016\0035Q\021AD\001\006g\016\fG.Y\005\003!5\021a!\0218z%\0264\027A\002\0
37j]&$h\bF\001\b\001")
public final class A {}

A 这个类没有默认构造函数,甚至没有任何构造函数,所以这么用反射是创建不了的。

好在Scala 实现了自己的反射库:scala-reflect,使用时需要引入单独的 jar 包:

// https://mvnrepository.com/artifact/org.scala-lang/scala-reflect
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.13.0"
// https://mvnrepository.com/artifact/org.scala-lang/scala-library
libraryDependencies += "org.scala-lang" % "scala-library" % "2.13.0"

Scala 的单例对象(Object)是特殊的单例实例,反射时需通过其类型符号直接获取实例。这么拿到的object实例并非直觉上以为的单例对象 demo.A,实际上是 demo.A$。

import scala.reflect.runtime.universe
val mirror = universe.runtimeMirror(getClass.getClassLoader)
// 注意用 staticModule 而非 staticClass
val objectSymbol = mirror.staticModule("demo.A")
// 2. 获取单例对象的镜像(直接获取实例)
val objectMirror = mirror.reflectModule(objectSymbol)
// 3. 获取实例
val instance = objectMirror.instance.asInstanceOf[A.type]
println(instance)    // demo.A$@535779e4, 实际上是 A$ 类
println(instance.i)  // 1

反射创建 Class实例

package demo

import scala.reflect.runtime.{universe => ru}

class MyClass(val name: String, val age: Int) {
  def greet(): Unit = println(s"Hello, I'm $name, $age years old")
}

object ReflectDemo {
  def main(args: Array[String]): Unit = {
    // 获取运行时镜像
    val mirror = ru.runtimeMirror(getClass.getClassLoader)
    // 1. 获取类的类型符号(需要类的全限定名)
    val classSymbol = mirror.staticClass("demo.MyClass")
    // 2. 获取类的构造器(默认获取主构造器)
    val constructorSymbol = classSymbol.primaryConstructor.asMethod
    // 3. 获取类的
    val classMirror = mirror.reflectClass(classSymbol)
    // 4. 获取构造器方法
    val constructor = classMirror.reflectConstructor(constructorSymbol)
    // 5. 调用构造器创建实例
    val instance = constructor("Alice", 30).asInstanceOf[MyClass]
    println(instance.getClass) // class demo.MyClass
    instance.greet()
  }
}
posted @ 2025-11-02 00:54  vonlinee  阅读(6)  评论(0)    收藏  举报