是否可以在运行时在 Java 中创建变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7478833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to create variables at runtime in Java?
提问by NullUserException
For example, say I wanted to "extract" String[] fruits = {"Pear", "Banana", "Apple"};
into three separate variables, eg:
例如,假设我想“提取”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";
How could I do that, ignoring the "Why the heck would you want to do that?"question that you might be urged to ask me.
我怎么能那样做,而忽略了“你到底为什么要那样做?” 你可能会被催促问我的问题。
Similar questions have been asked many times before, but the real answer was never given, because what the OP really needed was to use a different approach. That's fine, but is this possible at all?
类似的问题以前被问过很多次,但从未给出真正的答案,因为 OP 真正需要的是使用不同的方法。这很好,但这可能吗?
I have looked at reflection and it doesn't seem like there are any methods that would allow me even to add extra fields to an instance, let alone dynamically create locals.
我看过反射,似乎没有任何方法可以让我什至向实例添加额外的字段,更不用说动态创建本地变量了。
回答by Stephen C
Is it possible to create variables at runtime in Java?
是否可以在运行时在 Java 中创建变量?
The simple answer is No.
简单回答是不。
Java is a static language and does not support the injection of new variable declarations into an existing compiled program. There are alternatives (in order of decreasing usefulness / increasing difficulty):
Java 是一种静态语言,不支持将新的变量声明注入到现有的已编译程序中。有替代方案(按有用性递减/难度递增的顺序):
- Represent your "variables" as name / value pairs in a
Map
. Or come up with some other design that doesn't requirereal dynamic variables. - Use a scripting language that runs on the JVM and is callable from Java.
- Use some kind of templating mechanism to generate new source code containing the declarations, and compile and load it dynamically.
- Use a byte code manipulation library (e.g. BCEL) to create class files on the fly and then dynamically load them.
- 将您的“变量”表示为
Map
. 或者想出一些其他不需要真正动态变量的设计。 - 使用在 JVM 上运行并可从 Java 调用的脚本语言。
- 使用某种模板机制生成包含声明的新源代码,并动态编译和加载它。
- 使用字节码操作库(例如 BCEL)动态创建类文件,然后动态加载它们。
The first approach is the best. Java is a static language, and works best if you don't fight it. If this is a problem for you, maybe you are using the wrong language.
第一种方法是最好的。Java 是一种静态语言,如果您不与它作斗争,则效果最好。如果这对您来说是个问题,那么您可能使用了错误的语言。
The last two are difficult / complicated and have significant performance costs. They are almost certainly not going to help ...
最后两个是困难/复杂的,并且具有显着的性能成本。他们几乎肯定不会帮助......
回答by Alex Gitelman
The question is not why you want to do it but 'what are you going to do with it?'. So suppose at runtime variable with the name fruits2
magically appeared on the stack of your method. Now what? You had to know its name at compile time to take advantage of it. Reflection will not help you access local variables.
问题不是你为什么要这样做,而是“你打算用它做什么?”。因此,假设在运行时变量的名称fruits2
神奇地出现在您的方法堆栈中。怎么办?您必须在编译时知道它的名称才能利用它。反射不会帮助您访问局部变量。
Anyway, I would be interested if you described more detailed use case.
无论如何,如果您描述了更详细的用例,我会很感兴趣。
回答by Yevgeny Simkin
The way you phrased your question, people won't understand what you're asking. I believe (if I DO understand) the answer to your question (which should be phrased: "is it possible to dynamically create variables at run time") is "not as you've presented it".
你提出问题的方式,人们不会明白你在问什么。我相信(如果我理解的话)你的问题的答案(应该表述为:“是否可以在运行时动态创建变量”)是“不像你提出的那样”。
You're right, there's no analog to javascript's (very powerful, but slow and fraught with hazards "eval" function, in Java), and that is precisely what you would need to get this to do what you're hoping to do.
你是对的,没有类似于 javascript 的(在 Java 中非常强大,但缓慢且充满危险的“eval”函数),而这正是你需要让它做你希望做的事情。
The closest that exists is a hashmap (which is actually pretty close) where you can designate the key at run time, and then set the value. It's fairly versatile as you can have an map that will allow for whatever type you want stored in the field.
存在的最接近的是哈希图(实际上非常接近),您可以在运行时指定键,然后设置值。它非常通用,因为您可以拥有一张地图,允许您在字段中存储任何类型。
回答by avh
You're not going to be able to modify a class that's already been loaded into the JVM. However, you could conceivably use ASM < http://asm.ow2.org/> or BCEL < http://commons.apache.org/bcel/> to dynamically generate a new class that has the dynamically-defined fields.
您将无法修改已加载到 JVM 中的类。但是,您可以想象使用 ASM < http://asm.ow2.org/> 或 BCEL < http://commons.apache.org/bcel/> 来动态生成具有动态定义字段的新类。
Way more trouble than it's worth. Seriously, just use a HashMap!
麻烦多于值得。说真的,只需使用 HashMap!
回答by billybyte
Would Janino be useful for you?
Janino 对你有用吗?
Here's some code. I think it's close to what you want, but I'm not sure.
这是一些代码。我认为它接近你想要的,但我不确定。
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();
}
}
}
}
回答by oorosco
Can you perhaps elaborate, not sure what you're doing different here. Of course you can create three different strings. However i believe the syntax in java is string xx = new string("DDFD");
您能否详细说明,不确定您在这里做什么不同。当然,您可以创建三个不同的字符串。但是我相信java中的语法是 string xx = new string("DDFD");
Edit:
编辑:
By this i mean, what are you trying to change here. You can allocate memory dynamically therefore you can create "variables" dynamically. HOWEVER you cannot create a "variable" in the primitive fashion such as "int x = 0;" in run time, however you can add nodes to linked lists, resize arrays, etc during run time.
我的意思是,你想在这里改变什么。您可以动态分配内存,因此您可以动态创建“变量”。但是,您不能以原始方式创建“变量”,例如“int x = 0;” 在运行时,但是您可以在运行时将节点添加到链表、调整数组大小等。