Scala进阶(1)—— 反射 object 和 class
1. Scala 的 反射
关于 Scala 反射的具体内容,可以参考官方文档:https://docs.scala-lang.org/overviews/reflection/overview.html
这篇文章写一点自己的理解:
- 由于 Scala 编译出来的内容是与 Java 相同的字节码文件,所以可以使用 Java 反射的相关方法来实现 Scala 代码的反射。
- Scala 自己写了一套基于 Scala 的反射,具体的实现在 scala.reflect 这个 package 下面。
- 这篇文章主要介绍,反射 Scala 中的 class 和 object 类的方法。
先看基础代码:
package com.personal
object ProvisioningApp {
val strInObj = "123"
def sayHello(): Unit = println("say hello")
def sayHello2(from: String, to: String): Unit = println(from + " say hello, " + to)
}
class ProvisioningApp {
val strInClazz = "234"
def sayGoodbye(): Unit = println("say goodbye")
}
2. Java Style
2.1 使用 Java 的方式反射 Scala class
和反射 Java 的 class 步骤完全一致,所以不赘述,直接贴代码:
test("Should reflect Scala class in Java style") {
val app = new ProvisioningApp
val field = classOf[ProvisioningApp].getDeclaredField("strInClazz")
field.setAccessible(true)
field.set(app, "789")
app.strInClazz shouldBe "789"
val method = classOf[ProvisioningApp].getDeclaredMethod("sayGoodbye")
method.setAccessible(true)
method.invoke(app)
}

2.2 使用 Java 的方式反射 Scala object
Scala 中的 object,称之为 “伴生类”,想要反射获取它的类或者方法,首先要知道它编译之后是个什么东西:


通过 jd-gui,我们知道了 Scala object 的具体实现:
- 编译之后的类名是 "类名+$" 形式
- 属性的名字,有时会和在代码中定义的不同(在这个例子里面没有显现,具体原因我还不知道,比如这个 "strInObj", 有时候这个类名会变成 “$com.$personal.$$strInObj” 这样)
- 可以发现,这是一个使用静态代码块模式的单例,详见 https://www.cnblogs.com/jing-an-feng-shao/p/7501617.html
- 因此,暂时没有找到使用 Java 方式反射 Scala object 的方法
3. Scala style
- Scala 反射的核心是 scala.reflect.runtime.universe
- 很多东西自己也没有特别搞懂,内容参考了网上的博客:https://blog.csdn.net/feloxx/article/details/76034023
- 核心是通过 universe 对象,去依次获得 “Mirror” 这个东西
3.1 使用 Scala 方式反射 Scala class
步骤如下:
- 通过 universe 和 classLoader 找到 JavaMirror
- 通过 JavaMirror 和 实例化对象 获取 InstanceMirror
- 通过 universe 获取目标类的 TypeTag
- 通过 TypeTag 获取目标类的 TermSymbol or MethodSymbol
- 获取 FieldMirror or MethodMirror
- 反射执行
test("Should reflect Scala class in Scala type") {
import scala.reflect.runtime.universe
val app = new ProvisioningApp()
// JavaMirror
val classMirror = universe.runtimeMirror(getClass.getClassLoader)
// InstanceMirror
val instanceMirror = classMirror.reflect(app)
// TypeTag
val typeTag = universe.typeOf[ProvisioningApp]
// TermSymbol
val strInClazzSymbol = typeTag.decl(universe.TermName("strInClazz")).asTerm
val fieldMirror = instanceMirror.reflectField(strInClazzSymbol)
fieldMirror.set("789")
app.strInClazz shouldBe "789"
// MethodSymbol
val sayGoodbyeSymbol = typeTag.decl(universe.TermName("sayGoodbye")).asMethod
// MethodMirror and invoke action
val result = instanceMirror.reflectMethod(sayGoodbyeSymbol)() // No input parameters here
result shouldBe "Goodbye"
}
3.2 使用 Scala 方式反射 Scala object
与 Scala class 不同,反射 Scala object 核心是通过 staticModule 获取 ModuleMirror:
test("Should reflect Scala object in Scala style") {
import scala.reflect.runtime.universe
// JavaMirror
val classMirror = universe.runtimeMirror(getClass.getClassLoader)
// The ModuleSymbol for object
val staticMirror = classMirror.staticModule("com.personal.ProvisioningApp")
// ModuleMirror can be used to create instances of the class
val moduleMirror = classMirror.reflectModule(staticMirror)
// ObjectMirror can be used to reflect the members of the object
val objectMirror = classMirror.reflect(moduleMirror.instance)
// TermSymbol represents val, var, def and object declarations
val strInObjSymbol = moduleMirror.symbol.typeSignature.member(universe.TermName("strInObj")).asTerm
// FieldMirror can be used to get and set the value of the field
val fieldMirror = objectMirror.reflectField(strInObjSymbol)
fieldMirror.set("789")
ProvisioningApp.strInObj shouldBe "789"
val sayHelloSymbol = moduleMirror.symbol.typeSignature.member(universe.TermName("sayHello")).asMethod
val sayHelloSymbol2 = moduleMirror.symbol.typeSignature.member(universe.TermName("sayHello2")).asMethod
// MethodMirror and invoke action
objectMirror.reflectMethod(sayHelloSymbol)()
objectMirror.reflectMethod(sayHelloSymbol2)("Sai", "Gerrard") // Pass the input parameters one by one
}

Scala进阶(1)—— 反射 object 和 class的更多相关文章
- Scala进阶之路-反射(reflect)技术详解
Scala进阶之路-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala中的反射技术和Java反射用法类似,我这里就不一一介绍反射是啥了,如果对 ...
- Scala进阶之路-Scala中的高级类型
Scala进阶之路-Scala中的高级类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类型(Type)与类(Class)的区别 在Java里,一直到jdk1.5之前,我们说 ...
- [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦
[.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...
- Scala进阶之路-Scala中的枚举用法案例展示
Scala进阶之路-Scala中的枚举用法案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala中的枚举值和Java中的枚举值有点差别,不过使用起来也都差大同小异,我这 ...
- Scala进阶之路-Scala中的Ordered--Ordering
Scala进阶之路-Scala中的Ordered--Ordering 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 说道对象的比较,在Java中大家最熟悉不过的就是实现类本身实 ...
- Scala进阶之路-正则表达式案例
Scala进阶之路-正则表达式案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 废话不多说,正则大家都很清楚,那在Scala如何使用正则了?我们直接上个案例,如下: /* @au ...
- Scala进阶之路-进程控制之执行shell脚本
Scala进阶之路-进程控制之执行shell脚本 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 废话不多说,我这里直接放一个案例. /* @author :yinzhengjie ...
- Scala进阶之路-Spark底层通信小案例
Scala进阶之路-Spark底层通信小案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Spark Master和worker通信过程简介 1>.Worker会向ma ...
- Scala进阶之路-Scala高级语法之隐式(implicit)详解
Scala进阶之路-Scala高级语法之隐式(implicit)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们调用别人的框架,发现少了一些方法,需要添加,但是让别人为你一 ...
随机推荐
- SpringBoot源码解析
1.@SpringBootApplication springboot采用注解方式开发的,当创建了一个springboot项目时,在启动类上会有一个注解@SpringBootApplication,这 ...
- Python3.x 基础练习题100例(21-30)
练习21: 题目: 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个.以后每天早上都吃了前 一天剩下的一半零一个.到第10天早上 ...
- Python - Asyncio模块实现的生产消费者模型
[原创]转载请注明作者Johnthegreat和本文链接 在设计模式中,生产消费者模型占有非常重要的地位,这个模型在现实世界中也有很多有意思的对应场景,比如做包子的人和吃包子的人,当两者速度不匹配时, ...
- free命令查看内存
[root@jojo ~]# free -h total used free shared buff/cache available Mem: 991M 273M 64M 1.1M 653M 535M ...
- Airbnb JavaScript代码规范(完整)
类型Types 基本数据类型 string number boolean null undefined symbol const foo = 1; let bar = foo; bar = 9; co ...
- Java视频教程免费分享(网盘直接取)
Java基础 Java马士兵:链接:https://pan.baidu.com/s/1jJRvxGi密码:v3xb Java刘意:链接:https://pan.baidu.com/s/1kVZQCqr ...
- Codeforces Round #545 B. Circus
题面: 传送门 题目描述: 马戏团中一共有N个人(N是偶数),有的人会扮演小丑,有的人会表演杂技.给出每个人会什么,然后按照下列规则把这些人分成两组: 每个人只能在其中一组 两个组的人数相等(也就是把 ...
- 滑动窗口解决最小子串问题 leetcode3. Longest Substring Without Repeating Characters
问题描述: Given a string, find the length of the longest substring without repeating characters. Example ...
- 一键自签本地 TLSv3 多域名 SAN 域名证书工具 HTTPS(最新版 Chrome 浏览器策略测试通过)
一键自动生成本地自签名SAN域名证书工具 原生OpenSSL生成自签名SAN CA域名(V3签名),在Linux.MacOS系统下签发测试通过. 用于一键快速生成开发和测试场景证书,内部平台授权和私有 ...
- Salesforce LWC学习(三十二)实现上传 Excel解析其内容
本篇参考:salesforce lightning零基础学习(十七) 实现上传 Excel解析其内容 上一篇我们写了aura方式上传excel解析其内容.lwc作为salesforce的新宠儿,逐渐的 ...