String to function name java

using a String to call a function of a class?

now I am asking the user to enter an element symbol like H, He, Li, etc to search for its info but I think you have to use an actual object to call the showdetails() function like H.showdetails() but i still tried with the String entered by the user like this:

System.out.print("Enter the correct exact symbol to search:"); String sym=sc2.nextLine(); for(i=0; i > 

and undoubtedly sym.showdetails(); doesn’t work even if the name of the object and the symbol entered by the user is same. so now if I do H.showdetails(); it works but sym.showdetails(); doesn’t work even if sym is H . what can be done now?

s[i].showdetails(); is what you are looking for. You matched the user input String with a field of an object. You need to invoke the method on that particular object.

Side note: In Java, there is a widely accepted coding convention that class names should start with an uppercase letter. If a name consists of more than one word, the usual style would be camel case (first letter of each word upper case). So in your example the class name would be e.g. Elements , method names (which start with a lower case letter) e.g. showDetails()

Some reading: docs.oracle.com/javase/tutorial/collections/interfaces/map.html your key is the element symbol (for example H ), your value is the Element instance (for example Element hydrogen = new Element(1, «Hydrogen», 1.008); ), you fill the map, then you can do theMap.get(«H»).showDetails();

Читайте также:  Java string pattern test

1 Answer 1

In Java, a Map associates (or maps) one object (a key) to another (a value). There are different implementations of Maps in Java, but since you’re new, just use the HashMap implementation. It’s a good general purpose implementation when you don’t have to access the HashMap in multiple threads.

A simple way in your case would be to write a function that creates the map, populates it with your element classes, and then returns the fully populated map. After that, you can perform a lookup based on the element’s symbol.

e.g. (please note, I’ve put your class name in caps according to Java style (when in Rome!))

// add these lines to top of file import java.util.Map; import java.util.HashMap; // example population function public Map getElements() < Mapelements = new HashMap<>(); elements.put("H", new Element(1, "Hydrogen", 1.008)); // etc. return elements; > // Getting your map of data and using it. Map elements = getElements(); System.out.println(elements.get("H")); 

Another thing to keep in mind when you’re declaring a Map. You should tell Java what types the key and value are supposed to be. In this code we’re associating the element symbol (a string) with your element class, so we need to put that in angle braces. e.g.

Notice that the return type of the function matches the type of the variable elements .

There are two other things that are different about this example than the code in your question that you should take note of.

First, it uses a constructor to populate the element. A constructor is a like an initializer function with the same name as your class, and it can be used in conjunction with the new operator.

Second, it defines a toString() method. A toString() method returns a string representation of an object in Java. This is preferable to simply printing from within the class because it can be used in many more situations than printing from a method.

Источник

How can I map a String to a function in Java?

Couldn’t you do String to Method ? Then you can cache the methods you need to execute.

Solution 2

There aren’t any first-class standalone functions, but you can do what you want with an interface. Create an interface that represents your function. For example, you might have the following:

public interface ComputeString

Then you can create a Map object like you want in the first place. Using a map will be much faster than reflection and will also give more type-safety, so I would advise the above.

Solution 3

While you can’t have first class functions, there are anonymous classes which can be based on an interface:

interface ProcessingMethod < String method(); >Map methodMap = new HashMap(); methodMap.put("abc", new ProcessingMethod() < String method() < return "xyz" >>); methodMap.put("def", new ProcessingMethod() < String method() < return "uvw" >>); methodMap.get("abc").method(); 

Solution 4

This example uses an enum of named functions and an abstract FunctionAdapter to invoke functions with a variable number of homogeneous parameters without reflection. The lookup() function simply uses Enum.valueOf , but a Map might be worth it for a large number of functions.

Java Strings are Immutable - Here's What That Actually Means

14.10 Map Interface in Java Collection Framework

Java Map and HashMap Tutorial (Java Collections) | Key-Value Pair Entry #10.3

Java Nâng Cao 15 Map - HashMap

Map and HashMap in Java - Full Tutorial

How To Use String Methods

Java 65. Hiểu rõ cấu trúc Map của Java | Viết chương trình tra từ điển Anh - Việt

Java Examples : Convert List to Map in java with example?

Matt Ball

Comments

Currently, I have a bunch of Java classes that implement a Processor interface, meaning they all have a processRequest(String key) method. The idea is that each class has a few (say, <10) member Strings , and each of those maps to a method in that class via the processRequest method, like so:

class FooProcessor implements Processor < String key1 = "abc"; String key2 = "def"; String key3 = "ghi"; // and so on. String processRequest(String key) < String toReturn = null; if (key1.equals(key)) toReturn = method1(); else if (key2.equals(key)) toReturn = method2(); else if (key3.equals(key)) toReturn = method3(); // and so on. return toReturn; >String method1() < // do stuff >String method2() < // do other stuff >String method3() < // do other other stuff >// and so on. > 
  • My keys would have to be named the same as the method — or be named in a particular, consistent way so that it’s easy to map them to the method name.
  • This seems WAY slower than the if-else statements I have right now. Efficiency is something of a concern because these methods will tend to get called pretty frequently, and I want to minimize unnecessary overhead.

TL; DR: I’m looking for a clean, minimal-overhead way to map a String to some sort of a Function object that I can invoke and call (something like) getReturnType() on. I don’t especially mind using a 3rd-party library if it really fits my needs. I also don’t mind using reflection, though I would strongly prefer to avoid using reflection every single time I do a method lookup — maybe using some caching strategy that combines the Map with reflection.

Thoughts on a good way to get what I want? Cheers!

Couldn’t you do String to Method (java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.h‌​tml)? Then you can cache the methods you need to execute.

That would mean having an implementing class for every single function I want to invoke, which seems clunky and requires a bit of boilerplate for every single function. Doesn’t sound that awesome to me.

@Bears, yeah it is clunky, but you can construct anonymous classes, which should make it somewhat less clunky, like map.put(str,new ComputeString()>);

Источник

Can we get a method name using java.util.function?

I would like to get the string isEmpty . How can I do this? EDIT: the code of the method I created is this one:

public class EnumHelper < private final static String values = "values"; private final static String errorTpl = "Can't find element with value `` for enum using getter ()"; public static , U> T getFromValue(T enumT, U value, String getter) < @SuppressWarnings("unchecked") final T[] elements = (T[]) ReflectionHelper.callMethod(enumT, values); for (final T enm: elements) < if (ReflectionHelper.callMethod(enm, getter).equals(value)) < return enm; >> throw new InvalidParameterException(MessageFormat.format(errorTpl, value, enumT, getter)); > > 

The problem is I can’t pass as parameter T::getValue, since getValue is not static. And I can’t pass someEnumElem::getValue, since the get() will return the value of that element. I could use inside the for loop:

Supplier getterSupllier = enm:getValue; if (getterSupllier.get().equals(value))

but in this way getValue is fixed, I can’t pass it as parameter. I could use some third-party library to do an eval() , but I really don’t want to open that Pandora vase 😀 EDIT 2: Function does work with no parameters methods, but only in Java 11. Unluckily I’m stuck with Java 8.

@MCEmperor At the very least: For debugging, to not print «Checking elements for HelloWorld$$Lambda$1/471910020@548c4f57» , but «Checking elements for isEmpty» . That would be great.

@Marco13 that would mean a toString of some kind and an identity for lambdas or methods references, the designers did not do that on purpose IIRC.

@MCEmperor: It’s for enum s. I created a generic method that from an enum, a value and a getter name, it returns the enum element with that value, returned by the getter specified. The only finesse is that I want to extract the name of the getter from the getter itself, not passing a string, like «getValue». This is because if the getter change in the enum , the compiler informs me I have to change it also when I invoke this method.

So why don’t you make your method accept a Function rather than a getter name? Then, instead of trying to find out the getter name, just to search for the right method to invoke, call apply on the function, which will already invoke the right method.

@MarcoSulla could you add it (ideally, with the code) to the question? maybe we could come up with something.

4 Answers 4

string::isEmpty will be constructed by a method LambdaMetafactory.metafactory which has implMethod among its parameters.

final String methodName = implMethod.internalMemberName().getName(); 

would return a method name (here, «isEmpty» ) if we had access to the arguments passed to this factory method, and to implMethod in particular. The arguments generated by up-calls from the JVM that provides very specific information for the java.lang.invoke API.

For example, to initialise a DirectMethodHandle which string::isEmpty represents, the JVM will call the following method.

/** * The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help. * It will make an up-call to this method. (Do not change the name or signature.) * The type argument is a Class for field requests and a MethodType for non-fields. * 

* Recent versions of the JVM may also pass a resolved MemberName for the type. * In that case, the name is ignored and may be null. */ static MethodHandle linkMethodHandleConstant(Class callerClass, int refKind, Class defc, String name, Object type)

That name (exactly what you requested) will be put there by the JVM, and there is no means for us to access it. For now.

Источник

Convert String to SomeType in Java

Is there some simple way to do that, which i can’t figure out? Or maybe you say that it is bad and vicious idea, i appreciate any advice! Thank you!

3 Answers 3

You are basically aiming to create a function that will return an object whose class was passed as a parameter.

I know no general solution for this problem.

But there are some partial solutions that together, so I believe, will answer for what you are looking for:

A. Returned object is a numeric:

For int and float the solution is obvious:

int ival = Integer.parseInt(strParam); float fval = Float.parseFloat(strParam); 

B. Returned object class has a string constructor , i.e. a constructor receiving a single string parameter

parser.addOption("--input_path", MySpecialClass.class, true); 

Here you can use reflection to instantiate the required object by fetching and activating the constructor. Note: our code does not need to know the return class identity, but weather or not it has a string constructor:

Constructor stringConstructor = classObject.getConstructor(new Class[]); Object objectToReturn = stringConstructor.newInstance(stringParam); 

Finally combining the above gives us an argument processing function similar to this:

Object processAnyParam(String strParam, Class returnClass, boolean mandatory) < if (returnClass.equals(int.class)) < return Integer.parseInt(strParam); >else if (returnClass.equals(float.class)) < return Float.parseFloat(strParam); >else if (maybe other numeric types here. ) < >else < try < Constructor stringConstructor = classObject.getConstructor(new Class[]); > catch (NoSuchMethodException e) < // no string constructor; bail out.. return null; >return stringConstructor.newInstance(strParam); > > 

Thank you for detailed answer, there are many useful ideas, but biziclop’s answer seemed to me the most simple and reliable. I think I will use some combined variant

It’s not possible to convert without passing some method to convert the String to the right object type (assuming you don’t require all classes to have a constructor with String as parameter that you want to use to parse the String ). One possibility would be to pass Function objects to addOption , e.g.:

public void addOption(String optionName, Function valueConverter, boolean required) 
parser.addOption("--stringParameter", Function.identity(), true); // remains identical parser.addOption("--integerParameter", Integer::parseInt, true); // use Integer.parseInt(String) parser.addOption("--binaryIntParameter", s->Integer.parseInt(s, 2), true); // integer given in binary format parser.addOption("--fileParameter", s -> new File(s), true); // use File(String) constructor 

Your parse function the code converting the String to the object would contain something like this:

Map result = //. // . String key = //. String stringValue = //. Function converter = //. get the converter from where you stored it result.put(key, converter.apply(stringValue)); //. return result; 

Источник

Оцените статью