前置き
『Javaでもa == 1 && a == 2 && a == 3でtrueって出力させたい』のJavassistを使って変数aの値を書き換えるバージョンです。
- deaf_tadashiさんのJava でもa == 1 && a == 2 && a == 3でtrueって出力させたい(黒魔術編)
- https://twitter.com/backpaper0/status/956007834025635841
- https://twitter.com/tada_suzu/status/956009590818263046
ソース
EqualsA.java
package com.example;
public class EqualsA {
private int a;
public void execute() {
System.out.println("start");
if (a == 1 && a == 2 && a == 3) {
System.out.println(true);
} else {
System.out.println(false);
}
System.out.println("end");
}
}
EqualsMain.java
package com.example;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.expr.ExprEditor;
import javassist.expr.FieldAccess;
public class EqualsMain {
public static void main(String[] args) throws Exception {
convert();
new EqualsA().execute();
}
static void convert() throws Exception {
ClassPool classPool = ClassPool.getDefault();
CtClass cc = classPool.get("com.example.EqualsA");
cc.instrument(new ExprEditor() {
private int i = 1;
@Override
public void edit(FieldAccess f) throws CannotCompileException {
if (f.getFieldName().equals("a")) {
f.replace(String.format("$_ = %d;", i++));
}
}
});
cc.toClass();
}
}
ExprEditorではローカル変数は扱えないようですがフィールドは扱えました。
おまけ(Scala)
object EqualsA {
def main(args: Array[String]): Unit = {
val a = Int(1)
if (a == 1 && a == 2 && a == 3) {
println("true")
} else {
println("false")
}
}
case class Int(n: scala.Int) {
override def equals(other: Any) = true
}
}