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

时间:2011-09-20 00:26:15

标签: java variables dynamic

例如,假设我想将“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真正需要的是使用不同的方法。那没关系,但这有可能吗?

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

6 个答案:

答案 0 :(得分:14)

  

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

简单的答案是否。

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

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

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

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:1)

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

你是对的,没有类似于javascript的(非常强大,但是在Java中,包含危险的“eval”功能很慢而且充满了这种功能),这正是你需要做到这一点来做你希望做的事情要做。

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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();
    }

}

}

答案 5 :(得分:-1)

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

编辑:

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