是否可以在Java中动态生成变量名称?

M. *_*awy 5 java code-generation dynamic names

假设我需要生成变量来保存用户的一些输入(我不知道它们有多少).如果不使用Array,ArrayList(和其他类型的列表和地图),可我的代码生成(可以说)String有相似的名字(变量X倍String var001,String var002,String var003,等)?如果是,请提供示例代码.

Esk*_*ola 5

如果你真的想做类似的事情,可以通过使用ASM或其他库生成字节码来实现.

下面的代码将生成一个名为"foo.bar.ClassWithFields"的类,其中包含字段"var0"到"var99".当然除了反射之外没有办法访问这些字段,因为它们在编译时不存在而Java是静态类型语言.

import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;

import java.lang.reflect.Field;

public class GeneratedFieldsExperiment {

    public static byte[] generateClassWithFields(int fieldCount) throws Exception {
        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "foo/bar/ClassWithFields", null, "java/lang/Object", null);

        for (int i = 0; i < fieldCount; i++) {
            fv = cw.visitField(ACC_PUBLIC, "var" + i, "Ljava/lang/String;", null, null);
            fv.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.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }

    public static void main(String[] args) throws Exception {
        MyClassLoader loader = new MyClassLoader();
        Class<?> c = loader.defineClass("foo.bar.ClassWithFields", generateClassWithFields(100));

        System.out.println(c);
        System.out.println("Fields:");
        for (Field field : c.getFields()) {
            System.out.println(field);
        }
    }

    private static class MyClassLoader extends ClassLoader {
        public Class<?> defineClass(String name, byte[] b) {
            return defineClass(name, b, 0, b.length);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 它使用ASM库生成一个类 - 字节数组的格式与Java编译器生成的.class文件的格式相同 - 然后使用自定义类加载器将其加载到JVM.ASM在Java字节码级别工作(类似于汇编代码),因此要理解上面的代码,首先需要学习一些Java字节码(ASM的文档对此有好处:http://download.forge.objectweb.org/asm/ ASM-指南.pdf).一些其他字节码操作库可能比ASM更容易使用,因为它们比纯字节码更高级别.我认为Javassist就是这样一个库. (2认同)

gmh*_*mhk 2

以下是我实施并帮助我轻松修复解决方案的方法,没有太多障碍。

// 创建数组List

List accountList = new ArrayList(); 




for(int k=0;k < counter;k++){
        accountList.add(k, (String)flowCtx.getValueAt("transitId"+m));
}
Run Code Online (Sandbox Code Playgroud)

迭代循环并将对象添加到带有索引的数组列表中。

//在运行时借助索引检索对象

String a = accountList.get(i));
Run Code Online (Sandbox Code Playgroud)