菜鸟在这里,我想扩展类,获取类文字,将其用作类型参数,或强制转换为它。
目前我可以实例化我的 ASM 生成的类并通过反射调用它的方法,但是该类的类型错误。
是的,编译器直到运行时才知道类,但是在这种情况下,我对类没有什么不知道的,但是我怎样才能说服编译器呢?
我已经有了解决方法,但我仍然很好奇这种“类型欺骗”会涉及什么(反射?AST 操作?破解类型检查器?)。
我用“Java”标签问了一个类似的问题,发布到“Scala”,希望 scala 编译器目前是一个更热门的话题。非常感谢您的意见,-朱利安
--下面需要类类型的例子--
没有字节码生成:
class B {
val hello = "Hello B!"
}
object HelloScala {
def main(args: Array[String]): Unit = {
val b = new B
println(b.hello)
}
}
使用字节码生成:
HelloScala.scala:
object HelloScala {
def main(args: Array[String]): Unit = {
val b = DumpLoader.loadClass("B", BDump.dump())
//println(b.hello) //error: Value hello is not a member of Class[?0]
val b_ = b.getDeclaredConstructor().newInstance()
//println(b_.hello) //error: Value hello is not a member of Any
}
}
BDump.java 字节码生成代码:
import java.util.*;
import org.objectweb.asm.*;
//import org.objectweb.asm.attrs.*;
public class BDump implements Opcodes {
public static byte[] dump () throws Exception {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "B", null, "java/lang/Object", null);
{
av0 = cw.visitAnnotation("Lscala/reflect/ScalaSignature;", true);
av0.visit("bytes", "\u0006\u0001y1A!\u0001\u0002\u0001\u000b\u0009\u0009!IC\u0001\u0004\u0003\u001daT-\u001c9usz\u001a\u0001a\u0005\u0002\u0001\rA\u0011qAC\u0007\u0002\u0011)\u0009\u0011\"A\u0003tG\u0006d\u0017-\u0003\u0002\u000c\u0011\u00091\u0011I\\=SK\u001aDQ!\u0004\u0001\u0005\u00029\u0009a\u0001P5oSRtD#A\u0008\u0011\u0005A\u0001Q\"\u0001\u0002\u0009\u000fI\u0001!\u0019!C\u0001'\u0005)\u0001.\u001a7m_V\u0009A\u0003\u0005\u0002\u001655\u0009aC\u0003\u0002\u00181\u0005!A.\u00198h\u0015\u0005I\u0012\u0001\u00026bm\u0006L!a\u0007\u000c\u0003\rM#(/\u001b8h\u0011\u0019i\u0002\u0001)A\u0005)\u00051\u0001.\u001a7m_\u0002\u0002");
av0.visitEnd();
}
// ATTRIBUTE ScalaSig
{
fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, "hello", "Ljava/lang/String;", null, null);
fv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "hello", "()Ljava/lang/String;", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "B", "hello", "Ljava/lang/String;");
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn("Hello B!");
mv.visitFieldInsn(PUTFIELD, "B", "hello", "Ljava/lang/String;");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}