是否可以在Java中在运行时创建变量?

例如,假设我想“提取” String[] fruits = {"Pear", "Banana", "Apple"}; 分成三个独立的变量,例如:

 for (int i=0; i != fruits.length; ++i) { // of course there's no eval in Java eval("String fruit + i = " + fruits[i] + ";"); } // ie: code that creates something equivalent to the following declarations: String fruit0 = "Pear"; String fruit1 = "Banana"; String fruit2 = "Apple"; 

我怎么能这样做,忽略了“为什么你想要这样做?” 你可能会被问到我的问题。

之前已经多次提出过类似的问题,但是从未给出真正的答案,因为OP真正需要的是使用不同的方法。 那没关系,但这有可能吗?

我看过reflection,似乎没有任何方法可以让我甚至为实例添加额外的字段,更不用说动态创建本地。

是否可以在Java中在运行时创建变量?

简单回答是不。

Java是一种静态语言,不支持将新变量声明注入现有的编译程序。 有其他选择(按有用性降低/难度增加的顺序):

  • 将您的“变量”表示为Map名称/值对。 或者提出一些不需要真正动态变量的其他设计。
  • 使用在JVM上运行的脚本语言,可以从Java调用。
  • 使用某种模板机制生成包含声明的新源代码,并动态编译和加载它。
  • 使用字节代码操作库(例如BCEL)动态创建类文件,然后动态加载它们。

第一种方法是最好的。 Java是一种静态语言,如果你不打它,效果最好。 如果这对您来说是个问题,也许您使用的是错误的语言。

最后两个是困难/复杂的并且具有显着的性能成本。 他们几乎肯定不会帮忙……

问题不在于你为什么要这么做,而是“你打算用它做什么?”。 因此,假设在运行时变量名称fruits2神奇地出现在您的方法的堆栈上。 怎么办? 你必须在编译时知道它的名字才能利用它。 reflection不会帮助您访问局部变量。

无论如何,如果您描述更详细的用例,我会感兴趣。

你提出问题的方式,人们不会明白你在问什么。 我相信(如果我理解的话)你的问题的答案(应该用措辞:“是否有可能在运行时动态创建变量”)是“不像你提出的那样”。

你是对的,没有javascript的模拟(非常强大,但是在Java中,它很慢,充满了危险的“评估”function),而这正是你需要做到这一点来做你希望做的事情。

存在的最接近的是散列映射(实际上非​​常接近),您可以在运行时指定密钥,然后设置该值。 这是相当多才多艺的,因为你可以有一个地图,允许你想要存储在该领域的任何类型。

您无法修改已加载到JVM中的类。 但是,您可以设想使用ASM < http://asm.ow2.org/ >或BCEL < http://commons.apache.org/bcel/ >动态生成具有动态定义字段的新类。

比它的价值更麻烦。 说真的,只需使用HashMap!

Janino对你有用吗?

这是一些代码。 我认为它接近你想要的,但我不确定。

 package misc; import java.lang.reflect.InvocationTargetException; import org.codehaus.janino.CompileException; import org.codehaus.janino.ScriptEvaluator; import org.codehaus.janino.Parser.ParseException; import org.codehaus.janino.Scanner.ScanException; public class JaninoExample { public static void main(String[] args) { String in = " {\"Pear\", \"Banana\", \"Apple\"};"; try { ScriptEvaluator se = new ScriptEvaluator("return new String[]"+in,String[].class); try { String[] fruits = (String[])se.evaluate(new Object[]{}); for(String fruit:fruits){ System.out.println(fruit); } } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (CompileException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } catch (ScanException e) { e.printStackTrace(); } } 

}

你能否详细说明一下,不确定你在这里做的与众不同。 当然,您可以创建三个不同的字符串。 但是我相信java中的语法是字符串xx = new string(“DDFD”);

编辑:

我的意思是,你想在这里改变什么呢? 您可以动态分配内存,因此可以动态创建“变量”。 但是,你无法以原始方式创建“变量”,例如“int x = 0;” 但是在运行时,您可以在运行时将节点添加到链接列表,resize数组等。