I am trying to create a way to give a full method call as a string to a function, which then should try to actually call this method.
This should work with any type and any number and generally arbitrary parameters.
The class where the methods are declared is going to be fixed (probably given as an argument to this classes constructor)
Basically it should work, as if the contents of the String (whatever they might be) would be a line inside the function.
Obviously this function can only try to do this and would need to catch and handle all exceptions (eg. when that method doesn't exist in the given class).
Like this:
public class Thisclass{
String example = "Testmethod(1, 4.23, 'test')";
Class otherclass;
public void Thisclass(Class implementationClass){
this.otherclass = implementationClass;
}
//Calling myFunction like this: myFunction(example);
//Should result in this being called: otherclass.Testmethod(1, 4.23, "test");
public void myFunction(String input){
try{
//Something here
}
catch(Exception ex){
//Handle exceptions
}
}
}
I know how I could do this when I knew the number, type and order of the parameters using reflection, but can I do the same with an unknown number of parameters of unknown type and in an unknown order?
I would be ok with limiting the maximum total number of parameters to something relatively small (eg. 4 or 5), but I would like to leave the type and order of the parameters relatively unlimited.
It would also be ok to limit the types to something like int, float, double, char and String plus arrays of all these.
I know I could overload a method with all sorts of possible parameters, but that is very unpractical, as only allowing a maximum of 4 integers or integer arrays would already bring me up to 8 different versions and allowing a random mix of those two would already need 31 different implementations...
Is this even possible?
Edit:
The comments tell me, that some of you don't really understand what I want to do.
Basically I am parsing a HTML file to be rendered using opengl and I want to be able to make links or buttons in the HTML file execute some method, but I do not want to specify one method, but leave the methods to a different part of the project.
Think:Run Method where MyMethod can be an arbitrary Method. The only thing that is known about the method is that it is implemented in the class otherclass. After parsing the HTML I can get the value of the href attribute as a string, so basically "MyMethod(1, 4.23, 'test')".
For those that suggested that it would be easiest to create / copy a method for every possible combination and order of the data types mentioned above: I did a quick calculation and only accepting 1-4 parameters of the 5 types mentioned above in an arbitrary combination and order, would require over a million different versions of the method. I really doubt that creating all those and somehow not ending with missing or doubled methods at the end is faster than anything else.
The best suggestion so far is the one from saka1029, to basically create an all new java file and compile it using the compiler api and then to run it. I will look into that, as it seems to be the best idea so far.
In Java, assume you have a data object object with an attribute bar that you need to set with a value that is returned from a complex operation done in an external source. Assume you have a method sendRequestToExternalSource that send a request based on 'object' to the external source and gets an object back holding (among other things) the needed value.
Which one of these ways to set the value is the better practice?
void main(MyObject object) {
bar = sendRequestToExternalSource(object);
object.setBar(bar);
}
String sendRequestToExternalSource(MyObject object) {
// Send request to external source
Object response = postToExternalSource(object);
//Do some validation and logic based on response
...
//Return only the attribute we are interested in
return response.getBar();
}
or
void main(MyObject object) {
sendRequestToExternalSourceAndUpdateObject(object);
}
void sendRequestToExternalSourceAndUpdateObject(MyObject object) {
// Send request to external source
Object response = postToExternalSource(object);
//Do some validation and logic based on response
...
//Set the attribute on the input object
object.setBar(response.getBar());
}
I know they both work, but what is the best practice?
It depends on a specific scenario. Side-effects are not bad practice but there are also scenarios where a user simply won't expect them.
In any case your documentation of such a method should clearly state if you manipulate arguments. The user must be informed about that since it's his object that he passes to your method.
Note that there are various examples where side-effects intuitively are to be expected and that's also totally fine. For example Collections#sort (documentation):
List<Integer> list = ...
Collections.sort(list);
However if you write a method like intersection(Set, Set) then you would expect the result being a new Set, not for example the first one. But you can rephrase the name to intersect and use a structure like Set#intersect(Set). Then the user would expect a method with void as return type where the resulting Set is the Set the method was invoked on.
Another example would be Set#add. You would expect that the method inserts your element and not a copy of it. And that is also what it does. It would be confusing for people if it instead creates copies. They would need to call it differently then, like CloneSet or something like that.
In general I would tend to giving the advice to avoid manipulating arguments. Except if side-effects are to be expected by the user, as seen in the example. Otherwise the risk is too high that you confuse the user and thus create nasty bugs.
I would choose the first one if I have only these two choices. And the reason of that is "S" in SOLID principles, single responsibility. I think the job of doComplicatedStuff method is not setting new or enriched value of bar to MyObject instance.
Of course I don't know use case that you are trying to implement, but I suggest looking at decorator pattern to modify MyObject instance
I personally prefer the variant barService.doComplicatedStuff(object); because I avoid making copies
I am trying to write a console parser for a command line application and have it somehow call methods/access members of another class, to which it is not related. In my driver/main method, I create an instance of the console parser, and I pass it strings entered by the user from the console. I also create an instance of a data structure, lets say a tree, in the driver, which has specific methods and members. Obviously, any Console Parser object will not be able to call/access any of the tree's methods or members, as it is not linked to it (at least not without passing it a reference to the data structure itself). Is there anyway I can have methods in the Console parser object that say--
if (line.hasOption(x))
{ return thisMethod(); }
and then be able to simply execute whichever method is returned from the parser in the driver?
I have read about interfaces being java's workaround for passing methods as parameters, but that's not really what I'm after.
I have also looked into using a framework like Commons CLI, but want this to be a kind of 'during runtime' command interface, rather than running the program each time I want to issue a new command.
Either way, I figure I'll end up writing a lot of if/else statements somewhere, but is there a clean way to do this?
EDIT:
Ok, here's a better example:
ArrayList<String> example = new ArrayList<>();
/* PARSING */
ConsoleParser parser = new ConsoleParser();
Scanner input = new Scanner(System.in);
String parserArgs = input.nextLine();
while (parserArgs != "quit")
{
execute(parser.parse(parserArgs));
parserArgs = input.nextLine();
}
So the idea is to have a console (within the application), where I can type commands like 'add x' or 'contains x' which would then be assigned to 'parserArgs.' Then the command string would be passed to the ConsoleParser where it would be dissected and searched for valid commands. If the command is valid (and has necessary options/arguments), the parse() method of ConsoleParser would somehow return the method (or name of method) to main, along with any arguments that method needs. So if I want to add the string "foo" to my ArrayList, then at the console I could type 'add foo' and that would be passed to the parser, which would then return to main some kind of instruction that the add() method of ArrayList needs to be called on 'example' with the argument 'foo.' I Know this could be easily done with an arraylist, but I just use it here for simplicity.
You can do that by using reflection. You can read more about it here: https://docs.oracle.com/javase/tutorial/reflect/
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.
am having problem in Saving some data in my Java code.
I have like three different methods which do some respective tasks. Am calling these methods using Hessian from Php client. And am not calling this three methods at a time. Each method will create some arrays(contains strings, int, float), and some time i have to use those arrays which was created my previous methods call in this present method.
Is there any way i can save that Arrays(not in database), may be a List or Array which will not flush the memory unless i say soo..
Example
public class top{
Method1(){
String[] stringA = {some string data} ;
}
Method2(){
for(string data : stringA){
I use array of stringA from method1 without calling the whole method1. I need that string value to be save untill i flush it out.
}
}
}
This is not a complete code.. not even a code. Am just trying to explain the issue.
Any help please.
Thanks.
How about defining the stringA as a instance variable instead of a local variable ?
You could set up stringA as a local variable to your class.
public class SomeClass {
private String[] stringA;
public void method1(){
stingA = "something";
}
public void method2(){
for(string data : stringA){
I use array of stringA from method1 which out calling the whole method. I need that string value to be save untill i flush it out.
}
}
You could also use a ArrayList, instead of an array for your string. This will allow you to dynamically grow your list. If you want to "flush" it, you could just call the clear() method
ArrayList<String> myArr = new ArrayList<String>();
myArr.add("string1");
myArr.add("string2");
//clear the ArrayList
myArr.clear()
If you want to remember values between method calls, it should be a instance (class
level) variable. If yours is a web application, you can use session variables.
[Your code is not complete, actually its not even there. Posting complete code helps someone trying to answer to understand the problem correctly.]
I don't know anything about hessian, but it looks like that the component that handles the call is stateless.
I agree with Nivas' answer in this case.
However, should you need extra functionality (search, etc) with the storage and have some hardware resource to spend you can also use something like HSQLDB which have in-memory DB storage (very fast).