Java reflection: How to get methods with no parameters only - java

I'm working on a school assignment about Java reflection. The details are below:
Write a console program that asks the user for a class name, loads
that class and creates an instance of it. We assume that the class has
a constructor without any parameters. Then, the program prints out the
names and values of the public variables of the created object, and
also a list of the public methods that do not specify a parameter. The
program should let the user choose a method and execute that method on
the created object. Afterwards, the program should again show the
public variables with their values and allow the user to choose a
method, and so on. Use the following class to test your
implementation:
public class Counter {
public int c;
public void increment() { c++; }
public void decrement() { c--; }
public void reset() { c = 0; }
}
The problem I am having has to do with the following sentence: "list of the public methods that do not specify a parameter". Is there a way to list only methods with no parameters? I have used getMethods but I end up getting a lot of methods from the Object and Class superclasses with parameters.
For example the following code that I have written:
import java.lang.reflect.*;
import java.io.*;
public class Q1 {
public static void main(String[] args) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("What class would you like to run? ");
String className = reader.readLine();
Class c = Class.forName(className);
Object o = c.newInstance();
for (Field f : c.getFields())
System.out.println(f);
for (Method m : c.getMethods())
System.out.println(m);
} catch(IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
Outputs the following:
What class would you like to run? Counter
public int Counter.c
public void Counter.reset()
public void Counter.increment()
public void Counter.decrement()
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
Is there a way to get only the ones with no parameters to be printed? Also is my interpretation of the assignment details right in the first place? Or does the phrase "public methods that do not specify a parameter" possibly mean something else and I have entirely the wrong idea?

Have you looked at the API for the Method class? There's a method called getParameterTypes() that has the answer for what you're looking for, and the API states explicitly what this will return if there are no parameters. Just call this in your for loop on the Methods returned and you should be in like flint.

Just use the Method class' getParameterTypes function. If the return value is 0 then there are no parameters to that function. Key part from the Java doc:
getParameterTypes
public Class[] getParameterTypes()
Returns an array of Class objects that represent the formal parameter types, in declaration order, of the method represented by
this Method object. Returns an array of length 0 if the underlying
method takes no parameters.
Returns:
the parameter types for the method this object represents

Related

Simple pass of variable to new class, then output in Java

I've seen this question asked in several ways, but the code is usually specific to the user, and I get lost a little. If I'm missing a nice clear and simple explanation, I'm sorry! I just need to understand this concept, and I've gotten lost on the repeats that I've seen. So I've simplified my own problem as much as I possibly can, to get at the root of the issue.
The goal is to have a main class that I ask for variables, and then have those user-inputted variables assessed by a method in a separate class, with a message returned depending on what the variables are.
import java.io.*;
public class MainClass {
public static void main(String[] args) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
String A;
String B;
try {
System.out.println("Is A present?");
A = reader.readLine();
System.out.println("Is B present?");
B = reader.readLine();
Assess test = new Assess();
} catch (IOException e){
System.out.println("Error reading from user");
}
}
}
And the method I'm trying to use is:
public class Assess extends MainClass {
public static void main(String[] args) {
String A = MainClass.A;
String B = MainClass.B;
if ((A.compareToIgnoreCase("yes")==0) &&
((B.compareToIgnoreCase("yes")==0) | (B.compareToIgnoreCase("maybe")==0)))
{
System.out.println("Success!");
}
else {
System.out.println ("Failure");
}
}
}
I recognize that I'm not properly asking for the output, but I can't even get there and figure out what the heck I'm doing there until I get the thing to compile at all, and I can't do THAT until I figure out how to properly pass values between classes. I know there's fancy ways of doing it, such as with arrays. I'm looking for the conceptually simplest way of sending a variable inputted from inside one class to another class; I need to understand the basic concept here, and I know this is super elementary but I'm just being dumb, and reading what might be duplicate questions hasn't helped.
I know how to do it if the variable is static and declared globally at the beginning, but not how to send it from within the subclass (I know it's impossible to send directly from the subclass...right? I have to set it somehow, and then pull that set value into the other class).
In order to pass variables to an object you have either two options
Constructor - will pass parameter when creating the object
Mutator method - will pass parameters when you call the method
For example in your Main class:
Assess assess = new Assess(A, B);
Or:
Assess assess = new Assess();
assess.setA(A);
assess.setB(B);
In your Assess class you have to add a constructor method
public Assess(String A, String B)
Or setter methods
public void setA(String A)
public void setB(String B)
Also, Assess class should not extend the main class and contain a static main method, it has nothing to do with the main class.
Below there is a code example!
Assess.java
public class Assess {
private a;
private b;
public Assess(String a, String b) {
this.a = a;
this.b = b;
}
public boolean check() {
if ((A.compareToIgnoreCase("yes")==0) &&
((B.compareToIgnoreCase("yes")==0) ||
(B.compareToIgnoreCase("maybe")==0)))
{
System.out.println("Success!");
return true;
} else {
System.out.println ("Failure");
return false;
}
MainClass .java
public class MainClass {
public static void main(String[] args) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
String A;
String B;
try {
System.out.println("Is A present?");
A = reader.readLine();
System.out.println("Is B present?");
B = reader.readLine();
Assess test = new Assess(A, B);
boolean isBothPresent = test.check();
// ................
} catch (IOException e){
System.out.println("Error reading from user");
}
}
I think what you're looking for are method parameters.
In a method definition, you define the method name and the parameters it takes. If you have a method assess that takes a string and returns an integer, for example, you would write:
public int assess(String valueToAssess)
and follow it with code to do whatever you wanted with valueToAssess to determine what integer you wanted to return. When you had decided that i was the int to return, you would put the statement
return i;
into the method; that terminates the method and returns that value to the caller.
The caller obtains the string to be assesed, then calls the method and passes in that string. So it's more of a push than a pull, if you see what I mean.
...
String a = reader.readLine();
int answer = assess(a);
System.out.println("I've decided the answer is " + answer);
Is that what you're looking for?
A subclass will have access to the public members of the superclass. If you want to access a member using {class}.{member} (i.e. MainClass.A) it needs to be statically declared outside of a method.
public class MainClass {
public static String A;
public static String B;
...
}
public class Subclass {
public static void main(String[] args) {
// You can access MainClass.A and MainClass.B here
}
}
Likely a better option is to create a class that has these two Strings as objects that can be manipulated then passed in to the Assess class
public class MainClass {
public String A;
public String B;
public static void main(String[] args) {
// Manipulate A, B, assign values, etc.
Assess assessObject = new Assess(A, B);
if (assessObject.isValidInput()) {
System.out.println("Success!");
} else {
System.out.println("Success!");
}
}
}
public class Assess {
String response1;
String response2;
public Assess (String A, String B) {
response1 = A;
response2 = B;
}
public boolean isValidInput() {
// Put your success/fail logic here
return (response1.compareToIgnoreCase("yes") == 0);
}
}
First you don't need inheritance. Have one class your main class contain main take the main out of Assess class. Create a constructor or setter methods to set the variables in the Assess class.
For instance.
public class MainClass
{
public static void main(String[] Args)
{
Assess ns = new Assess( );
ns.setterMethod(variable to set);
}
}
I'm not 100% sure of your problem, but it sounds like you just need to access variables that exist in one class from a subclass. There are several ways...
You can make them public static variables and reference them as you show in your Assess class. However, they are in the wrong location in MainClass use
public static String A, B;
You can make those variables either public or protected in the parent class (MainClass in your example). Public is NOT recommended as you would not know who or what modified them. You would reference these from the sub-class as if present in the sub-class.
public String A, B; // Bad practice, who modified these?
protected String A, B;
The method that might elicit the least debate is to make them private members and use "accessors" (getters and setters). This makes them accessible programmatically which lets you set breakpoints to catch the culprit that is modifying them, and also let you implement many patterns, such as observer, etc., so that modification of these can invoke services as needed. If "A" were the path to a log file, changing its value could also cause the old log to close and the new one to be opened - just by changing the name of the file.
private String A, B;
public setA(String newValue) {
A = newValue;
}
public String getA() {
return A;
}
BUT ...
Your question says "send to the subclass", but confounded by your knowing how to do this using global variables. I would say that the simplest way is to provide the values with the constructor, effectively injecting the values.
There are other ways, however, your example shows the assessment performed by the constructor. If your Assess class had a separate method to perform the assessment, you would just call that with the variables as arguments.
Your example is confusing since both classes have main methods and the child class does the assessing - I would think you would want the opposite - Have MainClass extend Assess, making "MainClass an Assess'or", let main assign the Strings to Assess' values (or pass them as arguments) to the parent class' "assess" method ("super" added for clarity):
super.setA(local_a);
super.setB(local_b);
super.assess();
or
super.assess(A, B);

Accessing an annotation's value inside the method to which it is applied to

Question: Is there a way to access an annotation's value inside the method to which it is being applied to?
Example: Say I have an annotation like so:
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnnotation {
int value default 0;
}
Next, I have a class C with functions f1/f2 that use this annotation. The value is known up-front during compile time.
public class C {
#MyAnnotation(value = 1)
public void f1() {
// Is there a way to get the 'value=1' here??
g();
}
#MyAnnotation(value = -1)
public void f2() {
g();
}
}
And I have another function g that must print 'positive' or 'negative' or 'zero' based on the annotation's value.
public static void g() {
// Must print 'positive' or 'negative' or 'zero'
}
1) Is there a way for f1/f2 to 'capture' the annotation's value and pass it along to g() as a parameter?
2) My current solution to this problem is to do this:
Have an initialization step in g()'s class to iterate through all of C's functions and pre-construct a hashmap of function name to value (Eg: {'C.f1': 1, 'C.f2': -1}). To do this, I use getClass(), getMethods() and getAnnotations() and filter to have only use MyAnnotation's.
Change g()'s signature to accept class and method name and use that as a key to look in the hashmap. The new call in f1 will be g(this, "f1") <-- I explicitly write "f1" to avoid looking in the stack trace for the method name.
Needless to say, this is very ugly and I'm hoping there's a simpler way to do this. Thanks.
Edit: I am not using (and don't plan to) the Spring Framework for this project.
I'm not sure it's a good design choice to access the annotation information inside the annotated method. Annotations represents meta-information which is not a part of the program. Usually they are accessible by a program runner that creates objects and run methods via reflection.
If you want to pass an attribute or a property to a method you can simply define a parameter which can be set by your "runner" depending on the annotation value.
However, you can find out which class and method you are in using the Thread.currentThread().getStackTrace() method and then access the annotation information.
Here is an example showing both approaches. It shows how to locate the current method in the stack trace and how to run the program via reflection and pass the method parameter.
public class StackTrace {
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public static #interface MyAnnotation {
int value() default 0;
}
public static class C {
#MyAnnotation(value = 1)
public void f1() { g(); }
#MyAnnotation(value = -1)
public void f2() {
g();
}
}
public static class X {
#MyAnnotation(value = 1)
public static void x1(int param) { System.out.println("Param1: " + param);}
#MyAnnotation(value = -1)
public static void x2(int param) { System.out.println("Param2: " + param); }
}
private static void g() {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement traceElement = stackTraceElements[3];
try {
Class<?> type = Class.forName(traceElement.getClassName());
String methodName = traceElement.getMethodName();
Method method = type.getMethod(methodName);
System.out.println(methodName + ": " +
method.getAnnotation(MyAnnotation.class).value());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void boo() throws InvocationTargetException, IllegalAccessException {
for (Method m : X.class.getDeclaredMethods()) {
MyAnnotation annotation = m.getAnnotation(MyAnnotation.class);
if (annotation != null) {
m.invoke(null, annotation.value());
}
}
}
public static void main(String[] args)
throws InvocationTargetException, IllegalAccessException {
C c = new C();
c.f1();
c.f2();
boo();
}
}
Output:
f1: 1
f2: -1
Param1: 1
Param2: -1

How do I call a method that has a method as its argument?

Here is a piece of code I have: (what I am trying to do with it is: define a method "renamingrule" in my main class, instantiate a instance of my other class "renamescript" and call its rename method passing as a parameter the "renamingrule" method i've defined in the main class. Everything is well in the RenamScript class, no errors, but i dont know how to call the rename method of the script class from my main class/method. thanks)
public class RenameScript2 {
...
public void rename(Method methodToCall) throws IOException, IllegalAccessException, InvocationTargetException {
try
{
...
String command = "cmd /c rename "+_path+"\\"+"\""+next_file+"\" "
+"\""+methodToCall.invoke(next_file, next_index)+"\"";
p = Runtime.getRuntime().exec(command);
}catch(IOException e1) {} catch(IllegalAccessException IA1) {} catch(InvocationTargetException IT1) {} ;
}//end of rename
} //end of class
//=======================================
public class RenameScriptMain2 {
public static String RenamingRule(String input, int file_row)
{
String output = "renamed file "+(file_row+1)+".mp3";
return output;
}
public static void main(String[] args) throws IOException
{
RenameScript2 renamer = new RenameScript2();
renamer.setPath("c:\\users\\roise\\documents\\netbeansprojects\\temp\\files");
try{
renamer.rename(RenamingRule);
}catch(IOException e2) {};
System.out.println("Done from main()\n\n");
}
} //end of class
You get hold of the Method object through Class.getMethod method. Something like this:
RenameScript2.class.getMethod("rename", parameters);
However, I suggest you consider writing an interface for a class that can perform the renaming, instead of passing a Method.
Such interface could look like
interface RenameAction {
void performRename();
}
To wrap the script in a RenameAction object you would do something like
RenameAction action = new RenameAction() {
void performRename() {
// ...
String command = "cmd /c rename "+_path+"\\"+"\""+next_file+"\" "...
p = Runtime.getRuntime().exec(command);
// ...
}
};
You would then simply do like this:
public void rename(RenameAction action) {
action.performRename();
}
Firstly, aioobe is definitely correct, passing a Method object is a little ugly. I'll assume that you're stuck with it!
To get a method, you'll need to use reflection. The below code grabs the method called toString on the class Integer. It then invokes the toString method.
Method method = Integer.class.getMethod("toString");
Object o = method.invoke(new Integer(7));
System.out.println(o);
Static methods don't need to pass the first parameter to method.invoke
Method method = File.class.getMethod("listRoots");
System.out.println(method.invoke(null));
This shows the reason why you shouldn't use it. That string "toString" and "listRoots" are not refactorable. If someone renames a method, then instead of a compile-time error, you'll get a runtime exception thrown (hence the exceptions you'll need to catch, NoSuchMethodException and IllegalAccessException). It's also much slower to use reflection than to use normal code.
Here is how you should do:
Make class RenameScript2 abstract by adding an abstract method public static String RenamingRule(String input, int file_row)
Then have your main class RenameScriptMain2 extend above class RenameScript2 and provide implementation of the method RenamingRule().
Now inside main method create instance of the class RenameScriptMain2 and call method RenamingRule()

Calling parent method from within the parent class

Here's an excerpt from my code
package dictionary;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.regex.*;
public class IntelliCwDB extends CwDB {
public IntelliCwDB(String filename) {
super(filename);
}
#Override
public void add(String word, String clue) {
System.out.println("inelli");
}
}
And CwDB...
package dictionary;
import java.util.LinkedList;
import java.io.*;
import java.util.Scanner;
public class CwDB {
protected LinkedList<Entry> dict;
public CwDB(String filename) {
dict = new LinkedList<Entry>();
createDB(filename);
}
public void add(String word, String clue) {
System.out.println("cwdb");
dict.add(new Entry(word, clue));
}
protected void createDB(String filename) {
try {
BufferedReader f = new BufferedReader(new FileReader(filename));
while (f.ready()) {
this.add(f.readLine(), f.readLine());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the main() part I create a new IntelliCwDB object, which fires the execution of createDB().
The problem is that I want CwDB.createDB() to use it's own CwDB.add() method, not the one from IntelliCwDB. Is there any other neat solution than creating CwDB separately, then passing it into the constructor of IntelliCwDB just to rewrite the LinkedList<Entry> dict database?
You experienced one of the reasons why one should not call virtual methods from a constructor. For more details on this, see Effective Java 2nd Edition, Item 17: Design and document for inheritance or else prohibit it.
The simplest solution to your problem would be to split the base class method into a nonvirtual (final and/or private) one, and another, virtual, method, which calls the former in the base class implementation.
#aioobe was faster to provide an example to this :-)
You could solve it like this:
Create a private (or final) version of the CwDB.add, lets call it privateAdd.
Let the old add method in CwDB call this method instead.
Whenever you want to be sure that the CwDB-version of add is used, you simply call privateAdd instead.
Sample code
public class CwDB {
// ...
public void add(String word, String clue) {
privateAdd(word, clue);
}
private void privateAdd(String word, String clue) {
System.out.println("cwdb");
dict.add(new Entry(word, clue));
}
protected void createDB(String filename) {
// ...
// "Calling parent method from within the parent class" :-)
this.privateAdd(f.readLine(), f.readLine());
// ...
}
// ...
}
As #Péter Török correctly points out: You should never call a virtual method (directly or indirectly) from within a constructor. The reason is simple: The sub-class will get to run code before its super class (and itself) is initialized properly. (Whether or not it applies in this particular example stands to reason though.)
I would move the add method to addInternal in CwDB, and make a new add which calls addInternal. Then in the createDB method, call addInternal to get the correct method.
Eg.
class CwDB {
..
private void addInternal(String word, String clue) {
..
}
public void add(String word, String clue) {
addInternal(word, clue);
}
public void createDB(String filename) {
..
addInternal(w, c);
..
}
}

Java Pass Method as Parameter

I am looking for a way to pass a method by reference. I understand that Java does not pass methods as parameters, however, I would like to get an alternative.
I've been told interfaces are the alternative to passing methods as parameters but I don't understand how an interface can act as a method by reference. If I understand correctly an interface is simply an abstract set of methods that are not defined. I don't want to send an interface that needs to be defined every time because several different methods could call the same method with the same parameters.
What I would like to accomplish is something similar to this:
public void setAllComponents(Component[] myComponentArray, Method myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) { //recursive call if Container
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
} //end if node
myMethod(leaf);
} //end looping through components
}
invoked such as:
setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());
Edit: as of Java 8, lambda expressions are a nice solution as other answers have pointed out. The answer below was written for Java 7 and earlier...
Take a look at the command pattern.
// NOTE: code not tested, but I believe this is valid java...
public class CommandExample
{
public interface Command
{
public void execute(Object data);
}
public class PrintCommand implements Command
{
public void execute(Object data)
{
System.out.println(data.toString());
}
}
public static void callCommand(Command command, Object data)
{
command.execute(data);
}
public static void main(String... args)
{
callCommand(new PrintCommand(), "hello world");
}
}
Edit: as Pete Kirkham points out, there's another way of doing this using a Visitor. The visitor approach is a little more involved - your nodes all need to be visitor-aware with an acceptVisitor() method - but if you need to traverse a more complex object graph then it's worth examining.
In Java 8, you can now pass a method more easily using Lambda Expressions and Method References. First, some background: a functional interface is an interface that has one and only one abstract method, although it can contain any number of default methods (new in Java 8) and static methods. A lambda expression can quickly implement the abstract method, without all the unnecessary syntax needed if you don't use a lambda expression.
Without lambda expressions:
obj.aMethod(new AFunctionalInterface() {
#Override
public boolean anotherMethod(int i)
{
return i == 982
}
});
With lambda expressions:
obj.aMethod(i -> i == 982);
Here is an excerpt from the Java tutorial on Lambda Expressions:
Syntax of Lambda Expressions
A lambda expression consists of the following:
A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p,
which represents an instance of the Person class.Note: You
can omit the data type of the parameters in a lambda expression. In
addition, you can omit the parentheses if there is only one parameter.
For example, the following lambda expression is also valid:
p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
The arrow token, ->
A body, which consists of a single expression or a statement block. This example uses the following expression:
p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively,
you can use a return statement:
p -> {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have
to enclose a void method invocation in braces. For example, the
following is a valid lambda expression:
email -> System.out.println(email)
Note that a lambda expression looks a lot like a method declaration;
you can consider lambda expressions as anonymous methods—methods
without a name.
Here is how you can "pass a method" using a lambda expression:
interface I {
public void myMethod(Component component);
}
class A {
public void changeColor(Component component) {
// code here
}
public void changeSize(Component component) {
// code here
}
}
class B {
public void setAllComponents(Component[] myComponentArray, I myMethodsInterface) {
for(Component leaf : myComponentArray) {
if(leaf instanceof Container) { // recursive call if Container
Container node = (Container)leaf;
setAllComponents(node.getComponents(), myMethodInterface);
} // end if node
myMethodsInterface.myMethod(leaf);
} // end looping through components
}
}
class C {
A a = new A();
B b = new B();
public C() {
b.setAllComponents(this.getComponents(), component -> a.changeColor(component));
b.setAllComponents(this.getComponents(), component -> a.changeSize(component));
}
}
Class C can be shortened even a bit further by the use of method references like so:
class C {
A a = new A();
B b = new B();
public C() {
b.setAllComponents(this.getComponents(), a::changeColor);
b.setAllComponents(this.getComponents(), a::changeSize);
}
}
Since Java 8 there is a Function<T, R> interface (docs), which has method
R apply(T t);
You can use it to pass functions as parameters to other functions. T is the input type of the function, R is the return type.
In your example you need to pass a function that takes Component type as an input and returns nothing - Void. In this case Function<T, R> is not the best choice, since there is no autoboxing of Void type. The interface you are looking for is called Consumer<T> (docs) with method
void accept(T t);
It would look like this:
public void setAllComponents(Component[] myComponentArray, Consumer<Component> myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) {
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
}
myMethod.accept(leaf);
}
}
And you would call it using method references:
setAllComponents(this.getComponents(), this::changeColor);
setAllComponents(this.getComponents(), this::changeSize);
Assuming that you have defined changeColor() and changeSize() methods in the same class.
If your method happens to accept more than one parameter, you can use BiFunction<T, U, R> - T and U being types of input parameters and R being return type. There is also BiConsumer<T, U> (two arguments, no return type). Unfortunately for 3 and more input parameters, you have to create an interface by yourself. For example:
public interface Function4<A, B, C, D, R> {
R apply(A a, B b, C c, D d);
}
Use the java.lang.reflect.Method object and call invoke
First define an Interface with the method you want to pass as a parameter
public interface Callable {
public void call(int param);
}
Implement a class with the method
class Test implements Callable {
public void call(int param) {
System.out.println( param );
}
}
// Invoke like that
Callable cmd = new Test();
This allows you to pass cmd as parameter and invoke the method call defined in the interface
public invoke( Callable callable ) {
callable.call( 5 );
}
While this is not yet valid for Java 7 and below, I believe that we should look to the future and at least recognize the changes to come in new versions such as Java 8.
Namely, this new version brings lambdas and method references to Java (along with new APIs, which are another valid solution to this problem. While they still require an interface no new objects are created, and extra classfiles need not pollute output directories due to different handling by the JVM.
Both flavors(lambda and method reference) require an interface available with a single method whose signature is used:
public interface NewVersionTest{
String returnAString(Object oIn, String str);
}
Names of methods will not matter from here on. Where a lambda is accepted, a method reference is as well. For example, to use our signature here:
public static void printOutput(NewVersionTest t, Object o, String s){
System.out.println(t.returnAString(o, s));
}
This is just a simple interface invocation, up until the lambda1 gets passed:
public static void main(String[] args){
printOutput( (Object oIn, String sIn) -> {
System.out.println("Lambda reached!");
return "lambda return";
}
);
}
This will output:
Lambda reached!
lambda return
Method references are similar. Given:
public class HelperClass{
public static String testOtherSig(Object o, String s){
return "real static method";
}
}
and main:
public static void main(String[] args){
printOutput(HelperClass::testOtherSig);
}
the output would be real static method. Method references can be static, instance, non-static with arbitrary instances, and even constructors. For the constructor something akin to ClassName::new would be used.
1 This is not considered a lambda by some, as it has side effects. It does illustrate, however, the use of one in a more straightforward-to-visualize fashion.
Last time I checked, Java is not capable of natively doing what you want; you have to use 'work-arounds' to get around such limitations. As far as I see it, interfaces ARE an alternative, but not a good alternative. Perhaps whoever told you that was meaning something like this:
public interface ComponentMethod {
public abstract void PerfromMethod(Container c);
}
public class ChangeColor implements ComponentMethod {
#Override
public void PerfromMethod(Container c) {
// do color change stuff
}
}
public class ChangeSize implements ComponentMethod {
#Override
public void PerfromMethod(Container c) {
// do color change stuff
}
}
public void setAllComponents(Component[] myComponentArray, ComponentMethod myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) { //recursive call if Container
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
} //end if node
myMethod.PerfromMethod(leaf);
} //end looping through components
}
Which you'd then invoke with:
setAllComponents(this.getComponents(), new ChangeColor());
setAllComponents(this.getComponents(), new ChangeSize());
If you don't need these methods to return something, you could make them return Runnable objects.
private Runnable methodName (final int arg) {
return (new Runnable() {
public void run() {
// do stuff with arg
}
});
}
Then use it like:
private void otherMethodName (Runnable arg){
arg.run();
}
Java-8 onwards
Java 8 onwards, you can provide the implementation of the abstract method of a functional interface (an interface that has only one abstract method) using a lambda expression and pass the same to a method as a parameter.
#FunctionalInterface
interface ArithmeticFunction {
public int calcualate(int a, int b);
}
public class Main {
public static void main(String args[]) {
ArithmeticFunction addition = (a, b) -> a + b;
ArithmeticFunction subtraction = (a, b) -> a - b;
int a = 20, b = 5;
System.out.println(perform(addition, a, b));
// or
System.out.println(perform((x, y) -> x + y, a, b));
System.out.println(perform(subtraction, a, b));
// or
System.out.println(perform((x, y) -> x - y, a, b));
}
static int perform(ArithmeticFunction function, int a, int b) {
return function.calcualate(a, b);
}
}
Output:
25
25
15
15
ONLINE DEMO
Learn more about it from Method References.
I didn't find any example explicit enough for me on how to use java.util.function.Function for simple method as parameter function. Here is a simple example:
import java.util.function.Function;
public class Foo {
private Foo(String parameter) {
System.out.println("I'm a Foo " + parameter);
}
public static Foo method(final String parameter) {
return new Foo(parameter);
}
private static Function parametrisedMethod(Function<String, Foo> function) {
return function;
}
public static void main(String[] args) {
parametrisedMethod(Foo::method).apply("from a method");
}
}
Basically you have a Foo object with a default constructor. A method that will be called as a parameter from the parametrisedMethod which is of type Function<String, Foo>.
Function<String, Foo> means that the function takes a String as parameter and return a Foo.
The Foo::Method correspond to a lambda like x -> Foo.method(x);
parametrisedMethod(Foo::method) could be seen as x -> parametrisedMethod(Foo.method(x))
The .apply("from a method") is basically to do parametrisedMethod(Foo.method("from a method"))
Which will then return in the output:
>> I'm a Foo from a method
The example should be running as is, you can then try more complicated stuff from the above answers with different classes and interfaces.
Java do have a mechanism to pass name and call it. It is part of the reflection mechanism.
Your function should take additional parameter of class Method.
public void YouMethod(..... Method methodToCall, Object objWithAllMethodsToBeCalled)
{
...
Object retobj = methodToCall.invoke(objWithAllMethodsToBeCalled, arglist);
...
}
I did not found any solution here that show how to pass method with parameters bound to it as a parameter of a method. Bellow is example of how you can pass a method with parameter values already bound to it.
Step 1: Create two interfaces one with return type, another without. Java has similar interfaces but they are of little practical use because they do not support Exception throwing.
public interface Do {
void run() throws Exception;
}
public interface Return {
R run() throws Exception;
}
Example of how we use both interfaces to wrap method call in transaction. Note that we pass method with actual parameters.
//example - when passed method does not return any value
public void tx(final Do func) throws Exception {
connectionScope.beginTransaction();
try {
func.run();
connectionScope.commit();
} catch (Exception e) {
connectionScope.rollback();
throw e;
} finally {
connectionScope.close();
}
}
//Invoke code above by
tx(() -> api.delete(6));
Another example shows how to pass a method that actually returns something
public R tx(final Return func) throws Exception {
R r=null;
connectionScope.beginTransaction();
try {
r=func.run();
connectionScope.commit();
} catch (Exception e) {
connectionScope.rollback();
throw e;
} finally {
connectionScope.close();
}
return r;
}
//Invoke code above by
Object x= tx(() -> api.get(id));
Example of solution with reflection, passed method must be public
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Program {
int i;
public static void main(String[] args) {
Program obj = new Program(); //some object
try {
Method method = obj.getClass().getMethod("target");
repeatMethod( 5, obj, method );
}
catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
System.out.println( e );
}
}
static void repeatMethod (int times, Object object, Method method)
throws IllegalAccessException, InvocationTargetException {
for (int i=0; i<times; i++)
method.invoke(object);
}
public void target() { //public is necessary
System.out.println("target(): "+ ++i);
}
}
Use the Observer pattern (sometimes also called Listener pattern):
interface ComponentDelegate {
void doSomething(Component component);
}
public void setAllComponents(Component[] myComponentArray, ComponentDelegate delegate) {
// ...
delegate.doSomething(leaf);
}
setAllComponents(this.getComponents(), new ComponentDelegate() {
void doSomething(Component component) {
changeColor(component); // or do directly what you want
}
});
new ComponentDelegate()... declares an anonymous type implementing the interface.
Here is a basic example:
public class TestMethodPassing
{
private static void println()
{
System.out.println("Do println");
}
private static void print()
{
System.out.print("Do print");
}
private static void performTask(BasicFunctionalInterface functionalInterface)
{
functionalInterface.performTask();
}
#FunctionalInterface
interface BasicFunctionalInterface
{
void performTask();
}
public static void main(String[] arguments)
{
performTask(TestMethodPassing::println);
performTask(TestMethodPassing::print);
}
}
Output:
Do println
Do print
I'm not a java expert but I solve your problem like this:
#FunctionalInterface
public interface AutoCompleteCallable<T> {
String call(T model) throws Exception;
}
I define the parameter in my special Interface
public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {.......
//call here
String value = getSearchText.call(item);
...
}
Finally, I implement getSearchText method while calling initialize method.
initialize(getMessageContactModelList(), new AutoCompleteCallable() {
#Override
public String call(Object model) throws Exception {
return "custom string" + ((xxxModel)model.getTitle());
}
})
I appreciate the answers above but I was able to achieve the same behavior using the method below; an idea borrowed from Javascript callbacks. I'm open to correction though so far so good (in production).
The idea is to use the return type of the function in the signature, meaning that the yield has to be static.
Below is a function that runs a process with a timeout.
public static void timeoutFunction(String fnReturnVal) {
Object p = null; // whatever object you need here
String threadSleeptime = null;
Config config;
try {
config = ConfigReader.getConfigProperties();
threadSleeptime = config.getThreadSleepTime();
} catch (Exception e) {
log.error(e);
log.error("");
log.error("Defaulting thread sleep time to 105000 miliseconds.");
log.error("");
threadSleeptime = "100000";
}
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() {
// Do job here using --- fnReturnVal --- and return appropriate value
return null;
}
};
Future<Object> future = executor.submit(task);
try {
p = future.get(Integer.parseInt(threadSleeptime), TimeUnit.MILLISECONDS);
} catch (Exception e) {
log.error(e + ". The function timed out after [" + threadSleeptime
+ "] miliseconds before a response was received.");
} finally {
// if task has started then don't stop it
future.cancel(false);
}
}
private static String returnString() {
return "hello";
}
public static void main(String[] args) {
timeoutFunction(returnString());
}

Categories

Resources