例如,假设我想将“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真正需要的是使用不同的方法。那没关系,但这有可能吗?
我看过反射,似乎没有任何方法可以让我甚至为实例添加额外的字段,更不用说动态创建本地。
答案 0 :(得分:14)
是否可以在Java中在运行时创建变量?
简单的答案是否。
Java是一种静态语言,不支持将新变量声明注入现有的编译程序。有其他选择(按有用性降低/难度增加的顺序):
Map
中将您的“变量”表示为名称/值对。或者提出一些其他不需要需要真实动态变量的设计。第一种方法是最好的。 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;”但是在运行时,您可以在运行时将节点添加到链接列表,调整大小等等。