6

I want to create a class in Java from a classname and an variable number of arguments (i.e. an Object[] args with variable length). Is there any way to achieve that?

Basically, the method would look like this in Javascript

function createClass(classname, args) {
    protoObject = Object.create(window[classname].prototype);
    return window[classname].apply(protoObject,args) || protoObject;
}
// I want to be able to do this:
var resultClass = createClass("someClass", someArrayOfArgs);

A simpler function to only call a function would look like

function callFunction(functionName, args) {
    return window[functionName].apply(null,args);
}

Thanks!


For clarification, this would be some example usage in Javascript:

function multiplyResult(var1,var2) { 
    return var1*var2;
}
var result = callFunction("multiplyResult", ["5", "2"]); // == 10

function multiplyObject(var1,var2) { 
    var result = var1 * var2;
    this.getResult = function() { return result }; 
}
var result = createClass("multiplyObject", ["5", "2"]).getResult(); // == 10
Willem Mulder
  • 12,974
  • 3
  • 37
  • 62
  • Which exactly are you looking for? 1) The ability to use [varargs](http://docs.oracle.com/javase/6/docs/technotes/guides/language/varargs.html) in Java, or 2) The ability to [invoke a method via reflection](http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)) given its name and an array of arguments? Your title and question body don't quite align. – Rob Hruska Dec 15 '11 at 13:39
  • I am not looking for varargs. I want to *apply* an arbitrary list of parameters to a function. Edited my question as well :) – Willem Mulder Dec 15 '11 at 13:49
  • Use a vararg with Object. Thats the only way to have Java accept any number of arguments of unknown type for a method. – Stefan Dec 15 '11 at 14:44
  • Does this answer your question? [Java spread operator](https://stackoverflow.com/questions/46388620/java-spread-operator) – Krzysztof Atłasik Jun 05 '20 at 19:20

3 Answers3

9

It turns out that you can simply provide an Object[] to the invoke() function and that it will work exactly like .apply() in Javascript. Take the following function.

public int multiply(int int1, int int2) {
    return int1*int2;
}

From the same class, it works to call the function like

Object result = this.getClass().getDeclaredMethod("multiply",classes).invoke(this,ints);

with classes and ints being something like

Class[] classes = new Class[] {int.class, int.class};
Object[] ints = new Object[] {2,3};    
Zenoo
  • 12,670
  • 4
  • 45
  • 69
Willem Mulder
  • 12,974
  • 3
  • 37
  • 62
1

I think you need something like this. You can use reflection the invoke a method.

      Method method =  Class.forName("className").getMethod("methodName", Parameter1.class, Parameter2.class);

      MethodReturnType result= (MethodReturnType) method.invoke(Class.forName("className"), new Object[]{parameter1, parameter2});
erimerturk
  • 4,230
  • 25
  • 25
1

It goes like this:

 Class.forName("foo").clazz.getConstructor(<classes>).newInstance(... parameters)

but unlike javascript you have strong typing and have to say which constructor you like to have.

Konstantin Pribluda
  • 12,329
  • 1
  • 30
  • 35
  • That is because of overloading, not because of strong types. – Mathias Schwarz Dec 15 '11 at 13:50
  • I already use this if I have a known amount of parameters, but I want to be able to deal with any list or parameters (i.e. an Object[] args of variable size) and apply that to the class. Would that be possible? – Willem Mulder Dec 15 '11 at 13:53
  • Your option would be: 1) build array of classes in your array 2) iterate over constructors trying to find suitable constructor matching this array. This could be tricky because of last elipsis argument. DI containers like pico / spring do the same while autowiring. But you still have option to go for groovy - it runs on JVM and augments java – Konstantin Pribluda Dec 15 '11 at 14:06
  • Thanks for your answer! It turns out that I can simply provide an Object[] to getConstructor() and newInstance() and that will work. – Willem Mulder Dec 16 '11 at 12:39
  • not that easy. You will have to extract clases from your object first, and pack them into array in order. And if there is null object you are lost. In this case you will need more sophysticated constructor discovery strategy. ( just call all constructors with suitable amount of parameters, and catch InvalidArgumentException until you run out of constructors or have sucess would be one of them) – Konstantin Pribluda Dec 16 '11 at 12:45