Detecting whether a method/function exists in Java - java

Is there a method/function in Java that checks if another method/function is available just like function_exists(functionName) in PHP?
Here I am referring to a method/function of static class.

You can find out if a method exists in Java using reflection.
Get the Class object of the class you're interested in and call getMethod() with the method name and parameter types on it.
If the method doesn't exist, it will throw a NoSuchMethodException.
Also, please note that "functions" are called methods in Java.
Last but not least: keep in mind that if you think you need this, then chances are that you've got a design problem at hand. Reflection (which is what the methods to inspect the actual Java classes is called) is a rather specialized feature of Java and should not generally be used in business code (although it's used quite heavily and to some nice effects in some common libraries).

I suspect you're looking for Class.getDeclaredMethods and Class.getMethods which will give you the methods of a class. You can then test whether the one you're looking for exists or not, and what it's parameters are etc.

You can use Reflections to lookup if the method exists:
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
Class clazz = Test.class;
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals("fooBar")) {
System.out.println("Method fooBar exists.");
}
}
if (clazz.getDeclaredMethod("fooBar", null) != null) {
System.out.println("Method fooBar exists.");
}
}
private static void fooBar() {
}
}
But Reflection is not really fast so be careful when to use it (probably cache it).

Try using the Class.getMethod() method of the Class class =)
public class Foo {
public static String foo(Integer x) {
// ...
}
public static void main(String args[]) throws Exception {
Method fooMethod = Foo.class.getMethod("foo", Integer.class);
System.out.println(fooMethod);
}
}

Here my solution using reflection...
public static boolean methodExists(Class clazz, String methodName) {
boolean result = false;
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals(methodName)) {
result = true;
break;
}
}
return result;
}

You can use the reflection API to achieve this.
YourStaticClass.getClass().getMethods();

You can do this like this
Obj.getClass().getDeclaredMethod(MethodName, parameterTypes)

Related

Instantiate Java lambda function by name

I would like to create a lambda function in Java 8, get it's classname and then later instantiate the function again from its classname.
This is what I try:
import java.util.function.Consumer;
public class SimpleLambda
{
public static void call(String aLambdaClassName, String aArg) throws Exception
{
Class<Consumer<String>> lClass = (Class<Consumer<String>>) Class.forName(aLambdaClassName);
Consumer<String> newlamba = lClass.newInstance();
newlamba.accept(aArg);
}
public static void main(String[] args) throws Exception
{
{
// Attempt with a static method as lambda
Consumer<String> lambda = Host::action;
String classname = lambda.getClass().getName();
call(classname, "Hello world");
}
{
// Attempt with a locally defined lambda
Consumer<String> lambda = (s) -> { System.out.println(s); };
String classname = lambda.getClass().getName();
call(classname, "Hello world");
}
}
}
class Host {
public static void action(String aMessage) {
System.out.println(aMessage);
}
}
However, with this code (in both variants, using the static method reference and using the locally declared lambda), I get an exception:
Exception in thread "main" java.lang.ClassNotFoundException: mypackage.SimpleLambda$$Lambda$1/471910020
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at mypackage.SimpleLambda.main(SimpleLambda.java:12)
I would have expected that at I can at least re-instantiate the static method reference... nope, apparently not.
I have been using a similar approach with Groovy Closures and that worked nicely. So am I just doing something wrong with the Java 8 lambdas, or is it not possible to instantiate lambdas by name? I found some hints on the net that lambdas can be (de)serialized, so I would expect it should also be possible to instantiate them by name.
Well, it is a special property of Oracle’s JRE/OpenJDK to use “anonymous classes”, which can’t be accessed by name at all. But even without this, there is no reason why this ought to work:
Class.forName(String) tries to resolve the class via the caller’s ClassLoader. So even if lambda expressions were implemented using ordinary classes, there were not accessible if loaded via a different ClassLoader
Class.newInstance() only works if there is a public no-arg constructor. You can’t assume that there is a no-arg constructor nor that it is public
The assumption that the entire function’s logic has to reside in a single class is wrong. A counter-example would be java.lang.reflect.Proxy which generates interface implementations delegating to an InvocationHandler. Trying to re-instantiate such a proxy via its class name would fail, because you need the to pass the actual InvocationHandler instance to the proxy’s constructor. In principle, the JRE specific lambda expression implementation could use a similar pattern
Considering the points above, it should be clear that you can’t say that it worked with inner classes in general. There are a lot of constraints you have to fulfill for that.
Regarding Serialization, it works for serializable lambda expressions, because the persistent form is completely detached from the runtime implementation class, as described in this answer. So the name of the generated class is not contained in the serialized form and the deserializing end could have an entirely different runtime implementation.
Store the lambda instances in Map, keyed on the instance name. You can make the map globally available trough a singleton wrapper class (just watch out for synchronization issues).
class LambdaMap {
private HashMap<String, Consumer<String>> theMap;
private LambdaMap() {
theMap = new HashMap<>();
}
private static class INSTANCE_HOLDER {
private static LambdaMap INSTANCE = new LambdaMap();
}
public static LambdaMap getInstance() {
return INSTANCE_HOLDER.INSTANCE;
}
public Consumer<String> put(String key, Consumer<String> value) {
return theMap.put(key, value);
}
public static void Call(String aLambdaClassName, String aArg) {
Consumer<String> func = getInstance().theMap.get(aLambdaClassName);
if (func != null) {
func.accept(aArg);
}
}
}
class Host {
public static void action(String aMessage) {
System.out.println("Goodbye, " + aMessage);
}
}
public class GlobalLambdas {
public static void main(String[] args) {
LambdaMap.getInstance().put("print greeting", s -> {
System.out.println("Hello, " + s);
});
LambdaMap.getInstance().put("print goodbye", Host::action);
LambdaMap.Call("print greeting", "John");
LambdaMap.Call("print goodbye", "John");
}
}
run:
Hello, John
Goodbye, John

Java get compile-time safe method name

While working with the reflection class and annotations I have found that there is no clear way to reference a method name in a compile-time safe way. What I really want is to be able to reference a method within an annotation. Might look something like:
#CallAfter(method=Foo.class.foo())
void Bar() { ... }
At the moment you can only do this with strings, which is not compile time safe.. This is a problem because it undermines Java being statically typed. The only solution I have found is something like what is below. However this still does not help with referencing a method in an annotation. :(
public static String methodName = null;
public static void main(String[] args) {
// .foo() is compile-time safe
loadMethodName(IFoo.class).foo();
System.out.println(methodName);
}
public static <T> T loadMethodName(Class<T> mock) {
return (T) Proxy.newProxyInstance(mock.getClassLoader(), new Class[] { mock },
(obj, method, args) -> {
methodName = method.getName();
return null;
});
}
public interface IFoo {
Object foo();
}
Does anyone have any thoughts, comments, or a solution to this?
I write an AnnotationProcessor that can provide a compile-safe method reference. See it on github
It will give a compile error if the referenced method not exists.
And it works in eclipse, see the snapshot.

Expression that behaves differently inside a static method

I'm trying to write an expression or series of statements of Java source code that when written inside a static method evaluates to null, but if the method is non-static evaluates to this.
My initial idea was to 'overload' on static vs non-static, as below:
public class test {
public void method1() {
System.out.println(getThisOrNull());
}
public static void method2() {
System.out.println(getThisOrNull());
}
private static Object getThisOrNull() {
return null;
}
private Object getThisOrNull() {
return this;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
Unfortunately this isn't actually legal Java, you can't 'overload' like that and it just gives a compiler error:
test.java:14: error: method getThisOrNull() is already defined in class test
private Object getThisOrNull() {
^
1 error
Clearly in an ideal world I wouldn't write it like that to begin with, but the problem is this code will be generated automatically by a tool that is not really semantically or syntactically enough to distinguish between the static vs non-static case.
So, how can I write some source code that, although byte for byte identical compiles and behaves differently in depending on the presence of the static modifier for the method?
This can be achieved with a trick and a bit of help from Java's reflection facilities. It's ugly, but it works:
import java.lang.reflect.Field;
public class test {
public void method1() {
System.out.println(getThisOrNull(new Object(){}));
}
public static void method2() {
System.out.println(getThisOrNull(new Object(){}));
}
private static Object getThisOrNull(final Object o) {
for (Field f: o.getClass().getDeclaredFields()) {
if (f.getType().equals(test.class)) {
try {
return f.get(o);
}
catch (IllegalAccessException e) {
// Omm nom nom...
}
}
}
return null;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
This compiles and runs as hoped for:
test#183f74d
test#183f74d
null
The trick that makes this possible is the use of new Object(){}, which creates a new, anonymous class within the existing method that we're trying to figure out if it's static or not. The behaviour of this is subtly different between the two cases.
If the goal were just to figure out if the method is static or not we could write:
java.lang.reflect.Modifiers.isStatic(new Object(){}.getClass().getEnclosingMethod().getModifiers())
Since we want to get this (when available) we need to do something slightly different. Fortunately for us classes defined within the context of an instance of an object in Java get an implicit reference to the class that contains them. (Normally you'd access it with test.this syntax). We needed a way to access test.this if it existed, except we can't actually write test.this anywhere because it too would be syntactically invalid in the static case. It does however exist within the object, as a private member variable. This means that we can find it with reflection, which is what the getThisOrNull static method does with the local anonymous type.
The downside is that we create an anonymous class in every method we use this trick and it probably adds overheads, but if you're backed into a corner and looking for a way of doing this it does at least work.

Is it a good idea to use reflections in a Web application?

I have developed below code with the intention to remove if else conditions so that code cyclomatic complexity should be less.
For this I have used reflection api and wrote method which takes condition as an argument and called respective method on the condition name basis.
This works fine, I want to know is it a good idea to use reflection (This code) in web application, so that I am free from checking conditions.
For example in below code we have different method with prefix state ex: stateSUBMIT, stateWithdraw etc.
we can call stateSUBMIT method by passing only "SUBMIT".
public class Participate {
public String execute(String methodName) {
String st = null;
try {
Method method = this.getClass().getDeclaredMethod(
"state" + methodName);
method.invoke(this);
} catch (Exception e) {
e.printStackTrace();
}
return st;
}
public void stateSUBMIT() {
System.out.println("in SUBMIT");
}
public void stateWithdraw() {
System.out.println("in Withdraw");
}
public void state() {
System.out.println("in state ");
}
public void statenull() {
System.out.println("in null ");
}
public static void main(String[] args) {
Participate p = new Participate();
p.execute("SUBMIT");
}
}
This is valid code, but can be achieved without reflections.
Step One: Define an interface
public interface Command {
public void execute();
}
Step Two: Create Concrete Implementations
public class StateCommand implements Command {
public void execute() {
// Your code.
}
}
Step Three: Add a collection of these to your original class
private Map<String, Command> commands;
Step Four: Populate
public MyClass() {
commands = new HashMap<String, Command>();
commands.put("state", new StateCommand());
}
Get that class and execute
public String callMethod(String name) {
Command command = commands.get(name);
if(command != null) {
command.execute();
}
}
This is just a relatively simple alternative to using reflections, which should be considered as a last resort.
I would avoid it. There are better alternatives. You could pick one of all the numerous web frameworks or you could code something similar without reflection. For example, use a HashMap from the action (SUBMIT, ...) to an object that implements an interface. That way you can call a method with parameters without reflection, which is slow and which provides no compile-time validations. This is not a recommendation (go with a framework!), but it is a better way of doing what you are doing right now.
Your implementation is beneficial in case if you are doing for making this Generic approach for all other other classes in your project.Its good if you are having re usability of this in many other scenarios.
But if its only for specific implementation which is not generalized then there are many simple ways to do this job, because if you will use java reflections than there is some amount of time complexity involved which is comparatively less if you do it without using reflectns.

Unexpected Class.getMethod behaviour

A while ago I had a similar question when using Class.getMethod and autoboxing, and it made sense to implement this in your own lookup algorithm. But what really confused me a little was that the following is not working either:
public class TestClass
{
public String doSomething(Serializable s)
{
return s.toString();
}
public static void main(String[] args) throws SecurityException, NoSuchMethodException
{
TestClass tc = new TestClass();
Method m = tc.getClass().getMethod("doSomething", String.class);
}
}
String.class implements the Serializable interface and I really expected it to be included in the lookup method. Do I have to consider this in my own lookup algorithms as well?
EDIT: I did read the Javadoc, so let me emphasise the second part of the question: And if so do you have suggestions on how to do that fast (I already had to add some custom matching and converting algorithms and I don't want it to get too slow)?
As per your edit, you can make use of Class#isAssignableFrom(). Here's a basic kickoff example (leaving obvious (runtime) exception handling aside):
package com.stackoverflow.q2169497;
import java.io.Serializable;
import java.lang.reflect.Method;
public class Test {
public String doSomething(Serializable serializable) {
return serializable.toString();
}
public static void main(String[] args) throws Exception {
Test test = new Test();
for (Method method : test.getClass().getMethods()) {
if ("doSomething".equals(method.getName())) {
if (method.getParameterTypes()[0].isAssignableFrom(String.class)) {
System.out.println(method.invoke(test, "foo"));
}
}
}
}
}
This should print foo to stdout.
The javadoc for Class.getMethod is very explicit:
The parameterTypes parameter is an
array of Class objects that identify
the method's formal parameter types,
in declared order.
It offers no scope for subtypes.
getMethod isn't meant to find methods which are compatible with the given parameter types - it's meant to find methods with exactly the given parameter types.
You'd need to call getMethods() to find all the methods, then filter by name and number of parameters, then work out which of those are actually applicable.
Why would you call getMethod with String.class? Method signatures are exactly mapped. It doesn't make any sense to look up a method by the same criteria as if you will call them.

Categories

Resources