一段代碼
object ASD {
def main(args: Array[String]): Unit = {
def f(a: Any): Unit = {
println(a)
}
f("sfsfsfdsdfd")
}
}
如果我們想進行類似
ASD.main.f(xx)
或
ASD.f(xx)
的操作, 是否可行.
事實是殘酷的, 它告訴我們不可行.
那麼下面從反編譯角度來探究為什麼不可行:
首先我們打開編譯後的 class 檔案所在目錄
有2個檔案:
ASD.class
和
ASD$.class
ASD.class 節選
public final class ASD {
public static void main(String[] paramArrayOfString) {
ASD$.MODULE$.main(paramArrayOfString);
}
}
這個不重要
ASD$.class 節選
public final class ASD$ {
public static final ASD$ MODULE$;
private final void f$1(Object a) {
Predef$.MODULE$.println(a);
}
public void main(String[] args) {
f$1("sfsfsfdsdfd");
}
private ASD$() {
MODULE$ = this;
}
}
發現了嗎, 内部函數 f 被編譯為 私有的 final 方法f$1.
是以我們是無法從外部直接調用的.
但是理倫上我們是可以在 ASD 内部調用這個函數的.
是真的嗎,你也是這麼想的嗎.
我們試試
this.f$1(xxx)
但是很遺憾,
value f$1 is not a member of object ASD
編譯器看不懂我們意圖, 甚至IDE都直接否決了我們的異想.
那麼我們就是要調用這個方法怎麼辦呢.
難道 javac 就注定要成為遙不可及的高冷存在嗎.
我們難道就沒有更進一步的發展了嗎.
不, 偉大的 semi 醬告訴你,阻礙是不存在的.
“反射, JVM最大的外挂.”
val clazz = Class.forName("scala.ASD$")
val m = clazz.getDeclaredMethod("f$1", classOf[Object])
val o = clazz.getDeclaredField("MODULE$").get(null)
m.setAccessible(true)
m.invoke(o, "234234234".asInstanceOf[Object])
わぁ、ありがとう、せみちゃん。