Let\'s say that I need to generate variables to hold some input from the user (I don\'t know how many they are). Without using Array
, ArrayList
(an
This is not possible, but this is a perfect candidate for using one of the java collections.
Either use a dynamically allocated array:
String[] arr = new String[RUNTIME_SIZE];
Or a list which can change it's size during runtime:
List list = new ArrayList<String>();
Without using Array, ArrayList (and other kind of lists and maps)
Create files with these names. Hope that will work for your professor.
Or use the Java Scripting API mentioned before:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
engine.put("x", "hello"); // you can add any variable here
// print global variable "x"
engine.eval("println(x);");
// the above line prints "hello"
EDIT
Seems like internally this will use Maps :) Same with Properties file, Preferences API, or DOM Trees (they are using Vectors). So if your professor is so picky, use files.
If you really want to do something like that, you can do it through bytecode generation using ASM or some other library.
Here is code that will generate a class named "foo.bar.ClassWithFields" that contains fields "var0" to "var99". Of course there is no way other than reflection to access those fields, because they don't exist at compile time and Java is a statically typed language.
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);
}
}
}
Naming variables like that looks very 1980-ish. Meaning pre object oriented programming. So if you ever build software for a living - DON'T DO THIS.
But since it seems to be homework...
When we're talking about a named variable in Java, we mean something that's compiled. Unlike in some scripting languages there is no easy way to do this in Java.
So either you use a runtime compiled class like Markus Lausberg suggested.
Or you cheat and use the Java Scripting API and make use of the scripting languages. That way you can create code (in a String) at runtime.