can i store function names in final hashmap for execution? - java

I'm building an admin controller that work like a terminal emulator in Flex 4.5.
The server side is Red5 on a tomcat server using Java programming language.
When a user enter a command in his textinput, the command is sent to the red5, in red5 I check if the command exists and return a proper output or an error if the command or parameters don't match.
so for now i use if (command.equals("..") {} else if (command.equals(...
Is there a way to store the function name or a reference to the function that should be executed in each command and to execute it?
example:
// creating the hasmap
HashMap<String,Object> myfunc = new HashMap<String,Object>();
// adding function reference
myfunc.put("help",executeHelp);
or....
myfunc.put("help", "executeHelp"); // writing the name of the function
and then
void receiveCommand(String command, Object params[]( {
myfunc.get(command).<somehow execute the referrened function or string name ? >
}
any ideas?
thank you!

You could use reflection, but I suggest a easier way.
You can create an abstract class or interface with an abstract method execute. Example:
interface Command {
void execute(Object params[]);
}
class Help implements Command {
void execute(Object params[]) {
// do the stuff
}
}
Now your hashmap can be:
// creating the hasmap
HashMap<String,Command> myfunc = new HashMap<String,Command>();
// adding function reference
myfunc.put("help", new Help());
And then:
void receiveCommand(String command, Object params[]) {
myfunc.get(command).execute(params);
}

You can execute a function by name as follows:
java.lang.reflect.Method method;
try {
method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) {
// ...
} catch (NoSuchMethodException e) {
// ...
}
In the above snippet, param1.class, param2.class are the class types of the arguments of the method to execute.
Then:
try {
method.invoke(obj, arg1, arg2,...);
}
catch (IllegalArgumentException e) { }
catch (IllegalAccessException e) { }
catch (InvocationTargetException e) { }
There is lots more information about this here: http://java.sun.com/docs/books/tutorial/reflect/index.html

You can define an interface for your functions
interface Function {
public Object invoke(Object[] arguments);
}
and then public your code via this interface
public class Function1 implements Function {
public Object invoke(Object[] arguments) {
...
}
}
and store in the map
map.put("helpCommand", new Function1());
or store a reference using an anonymous class
Function theFunction = new Function() {
public Object invoke(Object[] arguments) {
return theRealMethod(arguments[0], String.valueOf(arguments[1]));
}
}
In the second example I showed how to use the anonymous class as an adaptor if the method you want to call has a different signature than your interface.

Related

How to call a method from a given string in Java

I am trying to reduce my code from using a bunch of if statements from getting a specified command and calling a method for it.
Instead, I want to try something that would take that command and call a method name with it
Something like this:
"get" + commandString + "Count"()
Instead of:
if (command == "something") {
callSomeMethod();
}
if (command == "somethingelse") {
callSomeOtherMethod();
}
...
Is there a way to call a method from a specified string? Or a better way to approach this problem.
This is the use-case for a switch case statement.
switch(command){
case "command1": command1(); break;
case "command2": command2(); break;
Using a string javascript style is fortunately impossible in Java. The comments links to answers how to use reflection to accomplish something similar. This is rarely a good solution.
we can use
java.lang.reflect.Method
Something like
java.lang.reflect.Method method;
try {
method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) { ... }
catch (NoSuchMethodException e) { ... }
The parameters identify the very specific method you need (if there are several overloaded available, if the method has no arguments, only give methodName).
And your possible solution can be like -
package com.test.pkg;
public class MethodClass {
public int getFishCount() {
return 5;
}
public int getRiceCount() {
return 100;
}
public int getVegetableCount() {
return 50;
}
}
package com.test.pkg;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
MethodClass classObj = new MethodClass();
Method method;
String commandString = "Fish";
try {
String methodName = "get" + commandString + "Count";
method = classObj.getClass().getMethod(methodName);
System.out.println(method.invoke(classObj)); //equivalent to System.out.println(testObj.getFishCount());
} catch (SecurityException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
Ref: How do I invoke a Java method when given the method name as a string?

Is there a solution to make a method call functions a dynamic amount of parameters by method references?

So, I have the following classes:
public class MainClass{
public void run(String infoOne, String infoTwo, String infoThree, String infoFour, String infoFive, String infoSix){
SomeClass someClass = new SomeClass();
someClass.runSomeMethod();
someClass.runSomeMethodTwo( infoOne);
someClass.runSomeMethodThree( infoThree, infoOne, infoSix);
someClass.runSomeMethodFour( infoTwo, infoFive);
someClass.runSomeMethodFive(infoThree, infoFive, infoOne, infoSix);
}
}
‌‌
public class SomeClass{
public boolean runSomeMethod(){
// do something
}
public boolean runSomeMethodTwo(String arg){
// do something
}
public boolean runSomeMethodThree(String argOne, String argTwo, String argThree){
// do something
}
public boolean runSomeMethodFour(String argOne, String argTwo){
// do something
}
public boolean runSomeMethodFive(String argOne, String argTwo, String argThree, String argFour){
// do something
}
}
As you can see it's a bunch of methods taking only Strings as parameters (but a different amount every time). What I want now is to wrap each single method in a try catch block and log some results. To do that I wanted to put a method in between that handles the logging:
log(SomeClass::runSomeMethodFour);
public void log(????? method, String...args){
try{
if(method.execute(args);
System.out.println("Success!");
} else {
System.out.println("Failed to execute!");
}
} catch (Exception e){
e.printStackTrace();
}
}
Is this possible in some way? To pass a dynamic number of arguments to a lambda function? Or could I do something with generics?
There is no need to create a complicated Reflection-based solution. Your problems stem from the unnecessary attempt to separate the method and the parameter arguments, instead of just encapsulating the entire action like
public class MainClass {
public void run(String infoOne, String infoTwo, String infoThree,
String infoFour, String infoFive, String infoSix) {
SomeClass someClass = new SomeClass();
log(() -> someClass.runSomeMethod());
log(() -> someClass.runSomeMethodTwo(infoOne));
log(() -> someClass.runSomeMethodThree(infoThree, infoOne, infoSix));
log(() -> someClass.runSomeMethodFour(infoTwo, infoFive));
log(() -> someClass.runSomeMethodFive(infoThree, infoFive, infoOne, infoSix));
}
public void log(BooleanSupplier method) {
try {
if(method.getAsBoolean()) {
System.out.println("Success!");
} else {
System.out.println("Failed to execute!");
}
} catch (Exception e ){
e.printStackTrace();
}
}
}
For the work of the log method, only the boolean return value is relevant, which matches the functional signature of BooleanSupplier.
JLS described Method Reference Expression:
The compile-time declaration of a method reference is the method to which the expression refers. In special cases, the compile-time declaration does not actually exist, but is a notional method that represents a class instance creation or an array creation. The choice of compile-time declaration depends on a function type targeted by the expression, just as the compile-time declaration of a method invocation depends on the invocation's arguments.
A method reference expression is compatible in an assignment context, invocation context, or casting context with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of the ground target type derived from T.
the method reference expression must be assign an exactly Function Interface at compile time. and Function Interface is a SAM Interface. so you can't bind a method handler dynamically by method reference expression at runtime.
but you can using reflection or invoke api to achieve it.
let see each method expression refer to a Function Interface in your SomeClass results in refers to different Function Interface type:
SomeClass it = new SomeClass();
BooleanSupplier first1 = it::runSomeMethod;//bound
Predicate<SomeClass> first2 = SomeClass::runSomeMethod;//unbound
Predicate<String> second1 = it::runSomeMethodTwo;//bound
BiPredicate<SomeClass, String> second2 = SomeClass::runSomeMethodTwo;//unbound
...
Hearing about "reflection" as a comment by Oliver Charlesworth I came up with the following solution:
public class Test {
static Test testLogger = new Test(); //This should be another class ofcourse, but it doesn't matter for this example
public static void main(String[] args) throws NoSuchMethodException, SecurityException{
Test test = new Test();
run(test, "something", "hi", "hai", "blaa");
}
public static void run(Object pageObjectModel, String methodName, String...arguments){
Class<String>[] args = new Class[arguments.length];
Arrays.fill(args, String.class);
try {
testLogger.log(pageObjectModel, pageObjectModel.getClass().getMethod(methodName, args), arguments);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
private void log(Object pageObjectModel, Method method, String...arguments) {
try {
if((Boolean)method.invoke(pageObjectModel, (Object[])arguments)){
System.out.println("Success!");
} else {
System.out.println("Fail!");
}
} catch (Exception e){
e.printStackTrace();
}
}
public boolean something(String one, String two, String three){
System.out.println(one+", "+two+", "+three);
return true;
}
}
This seems to be perfect for what I'm trying to achieve. Although I don't really like reflection due to having bad experiences with it (giving problems with obfuscated code) I think it's fine for this project.
Thanks for helping me in the right direction!

java run method on every element of arraylist

I have a large number of methods that need to be applied to each member of a given arrayList. The problem is that I'm at compile time uncertain which methods need to be applied to the arrayList and applying all of them each time (with a check) would be to costly (realtime application). So I'm now looking for a way to give the list a number of methods (a la function programming) and have them run. I know I could create special classes where each class uses only a uses a single method on each of it's members but there are roughly 50 methods so that would quickly escalate into 50 different classes. Which would add a lot of unnecessary complexity to the project. Is there another way?
So what I'm looking for is something like this:
public void runMethode(Function f,ArrayList<ObjectWithF> al){
for(ObjectWithF o:al){
o.f();
}
}
Does such a thing exist in java? Or am I going to have to either call all 50 methods or create 50 different classes? Or would a wrapper pattern work here?
In Java 8, this functionality is provided via the Stream#forEach(Consumer) method in a very convenient form.
If you don't have Java 8 yet, then you can create an interface, and create instances of anonymous classes implementing this interface. This is a bit more verbose, but still better than 50 named classes.
It may be beneficial to design this interface in a way that is structurally equal to the Consumer interface that is used in Java 8, so that it may simply be changed to use the Java 8 version once you do the update.
This example shows a comparison of both approaches:
import java.util.ArrayList;
import java.util.List;
class Person
{
void sayHello()
{
System.out.println("Hello from "+this);
}
void sayGoodbye()
{
System.out.println("Goodbye from "+this);
}
}
// This interface already exists as java.util.function.Consumer in Java 8
interface Consumer<T>
{
void accept(T t);
}
public class ForEachTest
{
public static void main(String[] args)
{
List<Person> persons = new ArrayList<Person>();
for (int i=0; i<5; i++)
{
persons.add(new Person());
}
runJava8(persons);
runJava7(persons);
}
private static void runJava8(List<Person> persons)
{
persons.stream().forEach(Person::sayHello);
persons.stream().forEach(Person::sayGoodbye);
}
private static void runJava7(List<Person> persons)
{
runMethodJava7(persons, new Consumer<Person>()
{
#Override
public void accept(Person person)
{
person.sayHello();
}
});
runMethodJava7(persons, new Consumer<Person>()
{
#Override
public void accept(Person person)
{
person.sayGoodbye();
}
});
}
public static void runMethodJava7(
List<Person> persons, Consumer<? super Person> consumer)
{
for(Person person : persons)
{
consumer.accept(person);
}
}
}
reflect can help.
see the code blow :
String obj = "abc";
String methodName = "toString";
try {
Method method = obj.getClass().getMethod("toString");
System.out.println(method.invoke(obj));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
we have a obj, and given a method, we can run this method on that object.
And, you can also consider define a interface, and all your objects in the list implements the interface. and iterate the list, call those methods which defined in the interface.
As of Java 8, use may use Consumer class:
public void runMethod(Consumer<ObjectWithF> consumer, ArrayList<ObjectWithF> al) {
for (ObjectWithF o : al) {
consumer.accept(o);
}
}
...
// for example
runMethod (o -> System.out.println (o), listOfObjectsWithF);
// or
runMethod (System.out::println, listOfObjectsWithF);
// or even
listOfObjectsWithF.forEach(System.out::println);
If it's not Java8, you may create this interface yourself and realize it for every method:
interface Consumer {
public void apply(ObjectWithF o);
}
public void runMethod(Consumer consumer, ArrayList<ObjectWithF> al) {
for (ObjectWithF o : al) {
consumer.apply(o);
}
}
...
runMethod(new Consumer() {
public void apply(ObjectWithF o) {
//for example
System.out.println (o.toString());
}
}, listOfObjectsWithF);

pass class name via context and use it to store static value in different class

The dialogue and the array displays just fine, I just want to be able to set the static variable from the originating class within the onClick that is in a method that is in a different class. All of the try, catch and
<?> were things that I put in at the insistence of the compiler:
public class Setter
{
public void myList(Context context, Class<?> thisclass, int arrayid, String choice)
{
return new AlertDialog.Builder(context)
.setItems(arrayid, new OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
setChoice(thisclass, context, arrayid, which, choice);
}
})
.create();
}
public void setChoice(Class<?> thisclass, Context context, int arrayid, int which, String choice)
{
String[] array = context.getResources().getStringArray(arrayid);
try
{
Field f = thisclass.getDeclaredField(choice);
f.set(null, array[which]);
}
catch (SecurityException e)
{
e.printStackTrace();
}
catch (NoSuchFieldException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
public class ClassA extends Activity
{
static String stringa;
Setter setted = new Setter();
...
public void onCreate()
{
super.onCreate();
...
AlertDialog thinga = setted.myList(this, getclass(), R.array.thinga, stringa).show();
...
}
}
When I select an item from the list, I get this from debugger:
ClassCache.findFieldByName(Field[], String) line: 438
Class.getDeclaredField(String) line: 666
Setter.setChoice(Class, Context, int, int, String) line: 45 // the line with the Field
I think I'm passing it the class wrong but this is a bit out of my current depth.
I have a number of different classes each with their own static Strings. I am passing the method below the name of the String (in choice) and the context of what I had hoped was the original class that called a method that called a method that led to the code below. I was hoping I could call context.choice = something and the machine would read that as ClassA.stringa = something; how do I do that?
Briefly, I want to have a list of items that the user can choose from be the content of a dialogue, and have their selection be saved and accessible to the class that called for the creation of the dialogue. Perhaps I'm going about this all wrong but I got tired of dealing with other 'kludges' involving using spinners to do the same thing.
Because onClick can't have non-final objects declared elsewhere (at least that is my understanding) I thought maybe I could get around that by calling to another method, setChoice that would store the value of whatever was chosen. I would definitively say this is a kludge and would love to be shown the light as to how you are supposed to deal with these things.
Java does not have closures, but you can get close with anonymous inner classes.
String output;
public void onCreate() {
Setter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
output = "selected";
}
});
}
See also this swing tutorial: http://download.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
Edit:
In spirit of your example, this should look like this:
public class Setter
{
public void setChoice(IsetString setter, String something)
{
setter.setString(something);
}
}
class ClassA extends Activity implements setString
{
static String stringa;
string polka = "dots";
Setter setted = new Setter();
...
public void onCreate()
{
super.onCreate();
...
setted.setChoice(new IsetString() {
#Override
public void setString(String s) {
stringa = s;
}
}, polka);
...
}
}
interface IsetString {
void setString(String s);
}
The short answer - use the Reflection API.
The long answer - you'll need to obtain access to the Fields of the desired Context Class. Once you gain access to the Field instances, you can set their values using the set() method; the API call is a bit tricky in that you'll need to pass in the object reference (the context object and not the context class) whose field you wish to modify.
It is necessary that your Context, choice and something parameters to the method, contain the necessary information to make this operation as simple as possible. In other words, the Context class might have to contain the actual Class object (or provides a way to get one) that contains the field.
You can use reflection for that. Suppose you context is class itself
public void setChoice(Class<?> context, String choice, String something)
{
try {
Field f = context.getDeclaredField(choice);
f.set(null, something);
} catch (....) {
}
}
Add proper exception handling
Note that first argument to set is null. That is only valid for static methods. So you may want to check that method is static using f.getModifiers().

How to make Virtual static methods or a functional equivalent with reflection in java

I have a tree of projectile classes I am trying to use some reflection to not implement every combination possible by hand when most of it would be copy paste or at best a lot of one liner virtual methods to override attributes.
Basically I have different weapon types that shoot in different patterns such as twin linked, alternating or just a single weapon, and a number of different projectiles such as missiles, bullets, sniper bullets.
The syntax is currently the flavor of:
public Bomber() {
weapons.add(new TwinLinkedWeapon<Missile>(Missile.class));
weapons.add(new Weapon<Bullet>(Bullet.class));
}
and Weapon looks like:
public class Weapon<T extends Projectile> {
long lastShot;
protected Constructor<? extends T> ctor;
public Weapon(Class<? extends T> projectileType) {
try {
ctor = projectileType.getDeclaredConstructor(actor.Actor.class);
} catch (SecurityException e) {
e.printStackTrace();
return;
} catch (NoSuchMethodException e) {
e.printStackTrace();
return;
}
lastShot = 0;
}
protected long getLastShotTime() {
return lastShot;
}
protected T newProjectile(actor.Actor ship){
T projectile = null;
try {
projectile = ctor.newInstance(ship);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return projectile;
}
protected void setLastShotTime(long time) {
lastShot = time;
}
public void shoot(Actor ship) {
//calculates time passed in milliseconds
if((System.currentTimeMillis() - getLastShotTime()) > T.getShotCoolDown()) {
game.Game.getActors().add(newProjectile(ship));
setLastShotTime(System.currentTimeMillis());
}
}
public String getWeaponName(){
return "" + getClass().getName() + " " + ctor.getName();
}
}
My issue is fairly simple to understand. On the line if((System.currentTimeMillis() - getLastShotTime()) > T.getShotCoolDown())
T is an abstract Projectile class instead of a derived class such as Bullet or Missile so when I call the static method T.getShotDelay() it always calls Projectile.getShotDelay() instead of the derived class.
My only solution is to make an instance of T with ctor and have that attribute be instance based instead of class based, but that seems like a 'less than ideal' solution.
I am new to java reflection and am unsure of the syntax to achieve this. I would appreciate any input.
You can get static methods from Class objects and invoke them on null, no need to call constructors. Just take the runtime class of T, that is:
T t = something;
Class<?> tClass = t.getClass();
Method staticMethod = tClass.getMethod("methodName");
staticMethod.invoke(null); // Static methods can be invoked on null.
You should use instance methods to get the functionality that you want.
Maybe you should consider using abstract factory pattern.
You can have IProjectileFactory interface that is implemented by MissileFactory and BulletFactory.
The factories are able to create new projectiles Missile and Bullet that implement the IProjectile interface. The projectile factories are given as parameters when you create new weapon instances (i.e. new TwinLinkedWeapon(new MissileFactory())).

Categories