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 (and other kind of lists and maps) can my code generate (lets say) String variables X times with names like (String var001, String var002, String var003, etc)? If yes, please provide sample code.
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);
}
}
}
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.
I haven't seen this answered yet, so I'll go for it. Write a program that just writes out Java source code. Most of it could be a template, and you would just have a loop that would write as many "string UserString003" type variables as you want.
Yes, this is horrible. But, as you said, it's a conceptual challenge problem for homework, so as long as no one mistakes this for "good" code, it might solve the issue.
Following is the way that i have implemented and helped me to fix my solution easily without much hurdles.
// Creating the array List
List accountList = new ArrayList();
for(int k=0;k < counter;k++){
accountList.add(k, (String)flowCtx.getValueAt("transitId"+m));
}
Iterating the loop and adding the objects into the arraylist with the index.
//Retrieving the object at run time with the help of the index
String a = accountList.get(i));
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.
I think you can generate a Java class at runtime or maybe use some script engine like Beanshell to generate the variables, you can even build the class by its bytecode. But I can't see how you will use that variables in your code, you must also create the code to work with that variables, or use reflection for that...
A naive solution:
create a class with all variables from var000 to var999 with a getter for each... but that's not really dynamically!
It looks like your professor is PHP-biased on the feature (Variable variables), so he was thinking if that was possible in java.
I personally don't think that this is possible, not in the way you are proposing. What can be done is the generation of classes at runtime, using tools like Javassist to make a more powerful reflection mechanism. So you can create a class that has the variables you want (string1, string2, etc.) at runtime.
However, don't forget that Variable variables is a really bad technique, which leads to bad code. It might be useful on very few cases, but I really don't recommend it.
You mean you want to generate variables named
var0, var1, var2 and use them in your code.
What is the difference when you use
var[0], var[1], var[2], .....
BUT
You can generate a Java class dynamically at runtime which implements an Interface you are using in your normal code. Then you compile this class using a compiler (For example Janino) and then load the class at runtime. Than you have created a class dynamically.
But i wonder, whether this is necessary for your usecase.
EDIT
I dont now for which usecase you are using this parameters but dynamic arguments you can use in Java like this example from here
// calculate average
public static double average( double... numbers )
{
double total = 0.0; // initialize total
// calculate total using the enhanced for statement
for ( double d : numbers )
total += d;
return total / numbers.length;
} // end method average
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>();
I do not know if I understood you correctly but if you are trying to use dynamically created names for your variables then yes, definitely - I am doing it like this:
// rndRng() creates random numbers in specified range
// this would output dynamically created variable like "name89"
String myDynamicalyCreatedName = "name" + Utils.rndRng(0, 100);
final UberShader $myDynamicalyCreatedName = new UberShader();
As you can see the point key here is the sign "$" that basically says "create variable name from the String that is given after this sign", and that's basically it - works like a charm for me for a few years now...hope it is what you wanted and that it helps a bit solving your problem.
Related
In python you can do this:
def f():
return 1, 2, 3
(foo, bar, baz) = f()
Is there an equivalent in java?
tl;dr: No, there isn't such a thing in Java.
You can assign initial values to variables like this:
int foo = 1, bar = 2;
But if your want (1, 2, 3) to be the result of a method call, this is not possible in Java. Java does not allow returning multiple values.
Python allows this:
def foo():
return 1, 2, 3
a, b, c = foo()
The main point, why this does not work in Java is, that the left hand side (LHS) of the assignment must be one variable:
Wrapper wrapper = WrapperGenrator.generateWrapper();
You can not assign to a tuple on the LHS as you can in Python.
If you want (1,2,3) to be the result of a method call, you can use an array:
int[] arr = {1,2,3};
I realize this is an old post, but I could point out a way that comes somewhat close to this.
Using the OP's example (This could obviously use multiple types instead of three ints, but I'm going with the original example),
class Trip{ int foo;int bar;int baz;} // After building this class, have your editor create a constructor for you!
public Trip() {
return new Trip(1,2,3);
}
Trip t = f()
Now at this point I realize you haven't actually ASSIGNED this to three local variables (or member variables) as you would have liked, however you do have a local variable you can use as though you had... like:
t.foo * t.bar + t.baz;
The advantages here are that this is quite terse, hardly more work than the python example and safer/clearer/easier to read; as is I'd be really happy with this!
Perhaps more important though is that as you go on you will realize that this mini-class should have been a real class all along since the values are going to be somewhat associated since they are from the same function!
You can change what you have to a real class with simple editor refactors--replace member access with getter/setter, make members private, extract the class into it's own file and you have a full class!
Chances are that you'll eventually figure out that your original function f() should have been a member (or constructor) of this class in the first place!
By the way, the disadvantage is that this will fully trigger some Java programmers that don't understand that rules were meant to be broken--if you have old coders who are insistent on stuff that seems pedantic (rule-obsessed) it's best not to try this because it'll make their head explode (all over you, most likely).
As I noted in this other question, if your goal is specifically to return multiple values from a function, in Java 16+ you can accomplish something similar to this using a record type:
record FooResult(int a, int b, int c) { }
FooResult produceFoo() {
return new FooResult(1, 2, 3);
}
/* ... */
var f = produceFoo();
System.out.println(f.a + "," + f.b + "," + f.c);
This will let you return any set of types, with named fields, at the expense of having to add a line to declare the record. This won't really help with assignments like (i, j) = (j, i) however.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why there is no way to pass by reference in java
Can anybody tell me why exactly Java does not provide C# "out" type feature when dealing with method parameters to pass by reference ?
I mean why would not it allow us to pass primitive data types like boolean for example, pass by reference. I have tried also with wrapper class java.lang.Boolean but still to no avail. It still wont allow me to pass variable by reference.
Is there any specific reason why Java still has not provided us with this even in version 7 ?
Java only has pass by value. This was a decision made when the language was designed.
Why doesn't java support pass by reference like C++
There is exactly one parameter passing mode -- pass by value -- and that helps keep things simple.
-- James Gosling, et al., The Java Programming Language, 4th Edition
If you want you can put your boolean as a member inside a mutable class (you can't use Boolean because it is immutable), and pass a reference to that class. Apache Commons even has a class called MutableBoolean that you can use.
Only the language design team could tell you why, but I believe the reason for not allowing "out" parameters might be something like: If you want a method that calculates two things, what you really want is either two methods, or one method that returns an object. This supposedly leads to better design and more maintainable code.
Note that you if you really want "out parameters" you can easily use arrays of one element. For example:
void div(int a, int b, int[] q, int[] r) {
if (q != null) q[0] = a/b;
if (r != null) r[0] = a%b;
}
// elsewhere:
int[] quotient = new int[1];
int[] remainder = new int[1];
div(4, 3, quotient, remainder);
This is just my opinion but I feel that the designers of Java believed they could simplify programming by eliminating features rather than making them more intuitive and easier to handle.
Short answer is that it's a design decision and there's nothing you can do with passing by reference that you couldn't do with passing object references by value.
As for your particular problem, there are two solutions:
A mutable wrapper class:
final class BooleanRef {
public boolean value;
}
And use it as:
// Function
void changeTheBoolean( BooleanRef b ){
b.value = true;
}
// Call:
BooleanRef b = new BooleanRef();
changeTheBoolean( b );
OR, (more hackish but more lightweight) wrap in an array:
// Function
void changeTheBoolean( boolean[] b ){
b[0] = true;
}
// Call:
boolean[] b = new boolean[1];
changeTheBoolean( b );
I am trying to learn a java-based program, but I am pretty new to java. I am quite confusing on the following two lines of java code. I think my confusion comes from the concepts including “class” and “cast”, but just do not know how to analyze.
For this one
XValidatingObjectCorpus<Classified<CharSequence>> corpus
= new XValidatingObjectCorpus<Classified<CharSequence>>(numFolds);
What is <Classified<CharSequence>> used for in terms of Java programming? How to understand its relationships with XValidatingObjectCorpusand corpus
For the second one
LogisticRegressionClassifier<CharSequence> classifier
= LogisticRegressionClassifier.<CharSequence>train(para1, para2, para3)
How to understand the right side of LogisticRegressionClassifier.<CharSequence>train? What is the difference between LogisticRegressionClassifier.<CharSequence>train and LogisticRegressionClassifier<CharSequence> classifier
?
These are called generics. They tell Java to make an instance of the outer class - either XValidatingObjectCorpus or LogisticRegressionClassifier - using the type of the inner object.
Normally, these are used for lists and arrays, such as ArrayList or HashMap.
What is the relationship between XValidatingObjectCorpus and corpus?
corpus is just a name given to the new XValidatingObjectCorpus object that you make with that statement (hence the = new... part).
What does LogisticRegressionClassifier.<CharSequence>train mean?
I have no idea, really. I suggest looking at the API for that (I think this is the right class).
What is the difference between LogisticRegressionClassifier.<CharSequence>train and LogisticRegressionClassifier<CharSequence> classifier?
You can't really compare these two. The one on the left of the = is the object identifier, and the one on the right is the allocator (probably the wrong word, but it is what it does, kind of).
Together, the two define an instance of LogisticRegressionClassifier, saying to create that type of object, call it classifier, and then give it the value returned by the train() method. Again, look at the API to understand it more.
By the way, these look like wretched examples to be learning Java with. Start with something simple, or at least an easier part of the code. It looks like someone had way too much fun with long names (the API has even longer names). Seriously though, I only just got to fully understanding this, and Java was my main language for quite a while (It gets really confusing when you try and do simple things). Anyways, good luck!
public class Sample<T> { // T implies Generic implementation, T can be substituted with any object.
static <T> Sample<T> train(int par1, int par2, int par3){
return new Sample<T>(); // you are calling the Generic method to return Sample object which works with a particular type of generic object, may it be an Integer or a CharSequence. --> see the main method.
}
public static void main(String ... a)
{
int par1 = 0, par2 = 0, par3 = 1;
// Here you are returning Sample object which works with a sequence of characters.
Sample<CharSequence> sample = Sample.<CharSequence>train(par1, par2, par3);
// Here you are returning Sample object which works with Integer values.
Sample<CharSequence> sample1 = Sample.<Integer>train(par1, par2, par3);
}
}
<Classified<CharSequence>> is a generic parameter.
LogisticRegressionClassifier<CharSequence> is a generic type.
LogisticRegresstionClassifier.<CharSequence>train is a generic method.
Java Generics Tutorial
I have really stuck on two Java related issues. One simple and one more difficult.
Regarding the creation of a 2D array, I initialize a table like this:
private String [][] table_of_classifiers = null;
and then, within a function, I fill its contents like this:
String [][] table_of_classifiers = {
{"x1","x","x","x","x"},
{"x2","x","x","x","x"},
{"x3","x","x","x","x"},
{"x4","x","x","x","x"},
{"x5","x","x","x","x"},
{"x6","x","x","x","x"},
};
But as you can guess the second table overwrites (locally) the first one, that is of course not what I want to do. What I do wrong? Note that the dimension of the table is not known from the beginning.
Regarding the creation of a 2D array, I initialize a table like this:
private String [][] table_of_classifiers = null;
Not really. This is the declaration and initialization of a variable that can point to a "2d array", "table" or more exact an "array of arrays" of Strings.
Unless you work with that fact that the variable can/will be null, initializing it to null is usually a bad idea, because you need to do extra work to check for null. Examples:
String[][] a;
// ...
String b = a[0][0];
This won't compile, unless a wasn't initialized in the mean time. This is a good thing, because you can avoid a potential bug.
String[][] a = null;
// ...
String b = a[0][0];
This will however will compile, and if you forgot to actually assign the variable a real array, the program will "crash" with a "null pointer exception" or you need to add additional code/work to check for null.
I fill its contents like this:
String [][] table_of_classifiers = {
{"x1","x","x","x","x"},
{"x2","x","x","x","x"},
{"x3","x","x","x","x"},
{"x4","x","x","x","x"},
{"x5","x","x","x","x"},
{"x6","x","x","x","x"},
};
You are not "filling" anything here. For something to be filled it must exist first, but you haven't created anything yet.
Here you are declaring a second variable of the same name, which is only possible if you are in a different scope that the first one, and in that case you are "hiding" ("shadowing") the original variable if it originally was accessible from this new scope.
But as you can guess the second table overwrites (locally) the first
one, that is of course not what I want to do. What I do wrong?
Which "first" table? There was no first table until now, only a first variable. The others have shown you what you need to do to assign the "table" to the original variable, by not using the "declaration" String[][] at the beginning of the line.
Otherwise it's impossible to say what you are "doing wrong" because you haven't really explained what you are attempting to do.
Note that the dimension of the table is not known from the beginning.
It's not? How/why are you using a array literal then? Literal arrays are for creating arrays of a fixed size with a fixed "prefilling".
What exactly do mean with "the beginning"? Isn't the size known when you are programming (during compile time) or when the program starts (at run time)?
If you get the size of the array during run time you can create a normal array with new:
int a = ...;
int b = ...; // Get the sizes from somewhere, e.g, user input
String[][] table_of_classifiers = new String[a][b];
// Now you have an "empty" table
If size "changes" during run time, then - depending on what you are actually attempting to do - then an array is the wrong tool and you should be using a List implementation such as ArrayList instead.
Regarding "eval", as the others say, Java is a compiled language making "eval" basically impossible. The is "reflection" or the use of Class types to achieve what you are hinting at, but you really need to explain much more extensively what you are trying to achieve, then it may be possible to help you here.
However reflection and CLass types are a complicated matter, and considering you are obviously struggling with the most basic Java concepts, you have a long way to go to until you will be able to do what you want to do.
Just do:
class Foo {
private String [][] table_of_classifiers = null;
void bar() {
table_of_classifiers = new String[][] {
{"x1","x","x","x","x"},
{"x2","x","x","x","x"},
{"x3","x","x","x","x"},
{"x4","x","x","x","x"},
{"x5","x","x","x","x"},
{"x6","x","x","x","x"},
};
}
}
Java doesn't have eval (because it's a compiled language), but it does have reflection. It's almost certainly not the best approach to whatever it is that you want to do, though.
Regarding your first problem: to assign to table_of_classifiers without redeclaring it, write:
table_of_classifiers = new String[][] {
{"x1","x","x","x","x"},
{"x2","x","x","x","x"},
{"x3","x","x","x","x"},
{"x4","x","x","x","x"},
{"x5","x","x","x","x"},
{"x6","x","x","x","x"},
};
Regarding eval . . . the problem is that the run-time doesn't have the names of scoped local variables, and although it can get the names of instance variables, it has to do that within the context of an object. It's possible to address these sorts of issues, but it's non-trivial, and will involve major compromises. I think you have to thoroughly understand how scoping works and how reflection works before you start figuring out what features eval will support, because otherwise you'll just be disappointed at all the requirements you give it that turn out to be impossible.
For example, say I wanted to "extract" String[] fruits = {"Pear", "Banana", "Apple"}; into three separate variables, eg:
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?
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.
Is it possible to create variables at runtime in 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):
Represent your "variables" as name / value pairs in a Map. Or come up with some other design that doesn't require real 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.
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.
The last two are difficult / complicated and have significant performance costs. They are almost certainly not going to help ...
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.
Anyway, I would be interested if you described more detailed use case.
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.
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.
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.
Way more trouble than it's worth. Seriously, just use a HashMap!
Would Janino be useful for you?
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();
}
}
}
Yes, for example, see Lombok library and specifically #log4j annotation that injects the log variable to the class
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");
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.