Java8 pass a method as parameter using lambda - java

I would like to create a class that store a list of methods references and then executes all of them using Java 8 Lambda but I have some problem.
This is the class
public class MethodExecutor {
//Here I want to store the method references
List<Function> listOfMethodsToExecute = new LinkedList<>();
//Add a new function to the list
public void addFunction(Function f){
if(f!=null){
listOfMethodsToExecute.add(f);
}
}
//Executes all the methods previously stored on the list
public void executeAll(){
listOfMethodsToExecute.stream().forEach((Function function) -> {
function.apply(null);
}
}
}
This is the class that I created for test
public class Test{
public static void main(String[] args){
MethodExecutor me = new MethodExecutor();
me.addFunction(this::aMethod);
me.executeAll();
}
public void aMethod(){
System.out.println("Method executed!");
}
}
But there is something wrong when I pass this::aMethod using me.addFunction.
What is wrong?

You should provide a suitable functional interface which abstract method signature is compatible with your method reference signature. In your case it seems that Runnable instead of Function should be used:
public class MethodExecutor {
List<Runnable> listOfMethodsToExecute = new ArrayList<>();
//Add a new function to the list
public void addFunction(Runnable f){
if(f!=null){
listOfMethodsToExecute.add(f);
}
}
//Executes all the methods previously stored on the list
public void executeAll(){
listOfMethodsToExecute.forEach(Runnable::run);
}
}
Also note that in static main method this is not defined. Probably you wanted something like this:
me.addFunction(new Test()::aMethod);

You can't refer to this in a static context as there is no this
me.addFunction(this::aMethod);
You need to refer to an instance or define your Function to take a Test object.
public void addFunction(Function<Test, String> f){
if(f!=null){
listOfMethodsToExecute.add(f);
}
}
and
me.addFunction(Test::aMethod);

Related

Java - List, array type thing of different type objects?

So I have a bunch of java classes that are structured like this
class Something {
public static String name;
public static String description;
public void run(String[] args);
}
The problem is, they are all different types. So if I try to make a HashSet of them and iterate over them
HashSet<Object> things = new HashSet<Object>();
things.add(new Something());
things.add(new Otherthing());
things.forEach(thing -> {
thing.run();
})
it gives this error
symbol: variable run
location: variable thing of type java.lang.Object
So how can I make an iterable Set of these objects and use their properties?
They need to be of the same type to be used like that. Luckily, we can fix this by implementing a fitting functional interface.
public class Something implements Runnable {
public String name;
public String description;
#Override
public void run() {
System.out.println("something");
}
}
Runnable has the method run() that takes no arguments and returns nothing (aka it has to do something).
So this works only if you're not actually going to be using the String array as an argument, as you don't include it in your calling of run(). However, if you do need it, you must change the implemented interface to Consumer instead of Runnable, with accept() instead, as this method actually takes an argument as opposed to run().
public class Main {
public static void main(String[] args) {
HashSet<Runnable> things = new HashSet<>();
things.add(new Something());
things.add(new Something2());
things.forEach(thing -> {
thing.run();
});
}
}
Now, we set the HashSet to the type of the implemented interface, and it works!
Here's the other class:
public class Something2 implements Runnable {
public String name;
public String description;
#Override
public void run() {
System.out.println("something2");
}
}
Now you can create as many classes as you want and have their methods do different things, while still being able to gather them in the same set(as long as they implement the same type)!
Side note: if you didn't need the attributes, you could've used lambda expressions to implement different versions of run() (or accept(), or any other functional interface-method).

Print statement not called in anonymous class passed to class constructor

I have two classes and one interface.
Interface:
public interface MyBirthdayEvent {
void itsMyBirthday();
}
First class:
public class MyBirthdayButton
{
public void addOnClickedListener(MyBirthdayEvent mbe){}
}
Second class:
public class MyBirthday {
private MyBirthdayButton myBirthdayButton = new MyBirthdayButton();
MyBirthday() {
myBirthdayButton.addOnClickedListener(new MyBirthdayEvent() {
public void itsMyBirthday() {
System.out.println("Happy Birthday");
}
});
}
}
Then in main, I have this:
public class TestThisStuff {
public static void main(String[] args) {
MyBirthday myBirthday = new MyBirthday();
}
}
As can be seen from the code, I am using an anonymous class in the MyBirthday constructor. In doing so, I am trying to get the string "Happy Birthday" to print to the console.
My problem is, when I call the MyBirthday constructor in main by making a new myBirthday object, I am not seeing the string "Happy Birthday" print to the console. Shouldn't it print to the console? If not, what I am doing wrong?
What you can do is this:
public interface MyBirthdayEvent {
void itsMyBirthday();
default void invoke() {
itsMyBirthday();
}
}
...
public class MyBirthdayButton
{
public void addOnClickedListener(MyBirthdayEvent mbe){
mbe.invoke();
}
}
...
Also, it will work without it, but use a lambda rather than an anonymous inner class. This looks much better.
MyBirthday() {
myBirthdayButton.addOnClickedListener(() ->
System.out.println("Happy Birthday"));
}
you can move System.out.println("some words")statement to your MyBirthdayEventconstructor
it didn't show in your console because you haven't invoke the method

Automatically call a method from unknown class

First of all, I am new in Java and I don't know yet a lot about it I just came up with this new idea.
Let's say I have a method methodCondition(String,String,String) where I want to be put in any class.
The scenario of code is below:
Where everything is started
public class MainClass{
public static void main(String... args)
{
//Whe everything started, call StartFunction from proccesshelper class to Start a Thread.
ProccessHelper phelper = new ProccessHelper();
phelper.StartFunction();
}
public void methodCondition(String data1, String data2, String data3){
//Do something about the data when this method is fire from Thread
}
}
A class where functions can call
public class ProccessHelper{
//Some function here
public void StartFunction(){
MyThread mythread = new MyThread();
Thread t = new Thread(mythread);
t.start();
}
//Some function here
}
A thread where methodCondition(String,String,String) is able to fire
public class MyThread implements Runnable {
volatile boolean StopThread = false;
public MyThread(){}
public void Stop(boolean stopThread){
this.StopThread = stopThread;
}
public void run(){
if(dontLoop){
while(true){
if(condition = true){
/*
* if the condition here is true then call "eventMethod" from any unkown class.
*/
methodCondition(String data1, String data2, String data3);
}
}
}
}
}
So my question is, it is possible that the MyThread can call methodCondition(String,String,String) in any class where it is register just like listening and waiting to be call?
Just like what I said, I don't know yet a lot in Java, I don't know what kind of function is this or if this is possible I just came up with this Idea.
So if anyone can tell,explain or give a link for any reference about what I am trying to achieve that will be very appreciated. I am also open for any clarification. Thank you!
If you want to call methodCondition from any class you must declare like static method. The statics methods can be called without instantiate the container class.
public static void methodCondition(String data1, String data2, String data3){
//Do something about the data when this method is fire from Thread
}
After declare like static you can call it directly:
MainClass.methodCondition(...);
All classes must be in the same package, or import MainClass where you want to use methodCondition.
If you don't know the class name, better put it in an interface and accept that interface as an input to your thread and call it from interface reference. This method could be inner to thread or can be a normal interface. Below is the example with inner interface.
Thread Code:
class MyThread implements Runnable {
interface interfaceName {
void methodName(String data1, String data2, String data3);
}
interfaceName interfaceReference = null;
// Other members declaration
private MyThread(interfaceName obj) {
interfaceReference = obj;
}
public static MyThread getInstance(interfaceName obj) {
if (obj == null) {
throw new NullPointerException();
}
return new MyThread(obj);
}
public void run() {
// Do your stuff
interfaceReference.methodName("", "", "");
// Do your stuff
}
}
Other Classes Example:
public class Temp implements MyThread.interfaceName {
public static void main(String[] args) {
Temp t = new Temp();
MyThread mt = MyThread.getInstance(t);
}
public void methodName(String data1, String data2, String data3) {
// Do your stuff
}
}
I am happy to found it and it is called Invoking Methods. And to be clear, what I really want is to find for specific name of method from unknown class and if it is exist then call it to fire specific task.
in Addition, the code I've done is below and it's work:
Class c=Class.forName("MainActivity");
Method m=c.getMethod("methodCondition", String.class, String.class, String.class); //The method has 3 String paramaters so I have to intialize it otherwise it will produce an error that the method was not found.
Object t = c.newInstance();
m.invoke(t,"Hello Word!", "this is", "to Invoke Method"); //Now invoke the method with the value or paramaters.

Java: Is it possible to always execute a certain function before other functions are called? (Like #Before in JUnit)

Is there a way to always execute a function before any other function of a class is called?
I have a class where I need to refresh some fields always before any function is called:
public class Example {
private int data;
public void function1(){
}
public void function2(){
}
//#BeforeOtherFunction
private void refresh(){
// refresh data
}
}
Because it seems to be bad programming, I don't want to call refresh at the beginning of every other function. Since other persons are going to work on this project as well, there would be the danger, that somebody extends the calls and doesn't call refresh.
JUnit has a solution for this with the #Before-Annotation. Is there a way to do this in other classes as well?
And by the way: If you know a programming pattern wich solves this problem in another way than executing a function everytime any function is called, that would be very helpful, too!
Use a dynamic proxy in which you can filter to those methods before which your specific "before" method should be called. And call it in those cases before dispatching the call. Please see the answer from How do I intercept a method invocation with standard java features (no AspectJ etc)?
UPDATE:
An interface is needed to be separated for the proxy. The refresh() method cannot remain private. It must be public and part of the interface (which is not nice here) to be able to be called from the proxy.
package CallBefore;
public interface ExampleInterface {
void function1();
void function2();
void otherFunction();
void refresh();
}
Your class implements that interface:
package CallBefore;
public class Example implements ExampleInterface {
#Override
public void function1() {
System.out.println("function1() has been called");
}
#Override
public void function2() {
System.out.println("function2() has been called");
}
#Override
public void otherFunction() {
System.out.println("otherFunction() has been called");
}
#Override
public void refresh() {
System.out.println("refresh() has been called");
}
}
The proxy which does the trick. It filters the needed methods and calls refresh().
package CallBefore;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ExampleProxy implements InvocationHandler {
private ExampleInterface obj;
public static ExampleInterface newInstance(ExampleInterface obj) {
return (ExampleInterface) java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new ExampleProxy(obj));
}
private ExampleProxy(ExampleInterface obj) {
this.obj = obj;
}
#Override
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result;
try {
if (m.getName().startsWith("function")) {
obj.refresh();
}
result = m.invoke(obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
The usage:
package CallBefore;
public class Main {
public static void main(String[] args) {
ExampleInterface proxy = ExampleProxy.newInstance(new Example());
proxy.function1();
proxy.function2();
proxy.otherFunction();
proxy.refresh();
}
}
Output:
refresh() has been called
function1() has been called
refresh() has been called
function2() has been called
otherFunction() has been called
refresh() has been called
This may not solve your exact problem but at least could be a starting point if you are allowed considering a re-design. Below is a simple implementation but with some small touches I believe you can achieve a more elegant solution. BTW, this is called Dynamic Proxy Pattern.
First thing you need is an interface for your class.
public interface Interface {
void hello(String name);
void bye(String name);
}
public class Implementation implements Interface {
#Override
public void hello(String name) {
System.out.println("Hello " + name);
}
#Override
public void bye(String name) {
System.out.println("Bye " + name);
}
}
Then java.lang.reflect.Proxy class comes to help. This class is able to create an instance for a given interface at runtime. It also accepts an InvocationHandler which helps you to capture method calls and looks like this.
public class InvocationHandlerImpl implements InvocationHandler {
private final Object instance;
public InvocationHandlerImpl(Object instance) {
this.instance = instance;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
try {
System.out.println("Before");
result = method.invoke(instance, args);
System.out.println("After");
} catch (Exception e){
e.printStackTrace();
throw e;
} finally {
System.out.println("finally");
}
return result;
}
}
After all your client code will look like this.
Interface instance = new Implementation();
Interface proxy = (Interface)Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[] { Interface.class },
new InvocationHandlerImpl(instance));
proxy.hello("Mehmet");
proxy.bye("Mehmet");
Output for this code is
Before
Hello Mehmet
After
finally
Before
Bye Mehmet
After
finally
I would define getters for every field and do the refreshment inside the getter. If you want to avoid unrefreshed access to your private fields at all, put them in a superclass (together with the getters which call refresh).
Depending on your project structure, it may be also sensible to introduce a separate class for all data that is regularly refreshed. It can offer getters and avoid that anyone accesses the non-refreshed fields.
Not in Java SE, but if you are using Java EE, you could use interceptors.
For standalone applications, you could consider using a bytecode manipulation framework, like javassist.
You can have a protected getter method for data. Access getData method instead of using data field. Child classes will see only getData and will have updated data every time.
public class Example {
private int data;
public void function1(){
}
public void function2(){
}
protected int getData(){
refresh();
return data;
}
//#BeforeOtherFunction
private void refresh(){
// refresh data
}
}
It is better to write another method which will be made protected(accessible to the child classes) which will call first the refresh method and then call the function.
This way the data would be refreshed before the function is called everytime(As per your requirement).
eg:
protected void callFunction1(){
refresh();
function();
}
Thanks,
Rajesh
You should use Decorator in this case. Decorator is a good choice for something like interceptor. Example here: https://msdn.microsoft.com/en-us/library/dn178467(v=pandp.30).aspx

How do I pass objects along from my Main class to other classes

I'm learning to code java and I encountered some problems in which I could use help understanding how things work.
I've made a list containing "Images", on my Main class, called "myList".
public class Main{
public static void main(String[] args) {
List<Images> myList = new ArrayList<Images>();
...
And I want to access it on this "System" class. But it doesn't seem to let me.
The plan is to access a position (the 3rd, in this example) on the given list (list.get(2)).
So I created the method "work".
//Example
public class System{
public static boolean work(List<Images> list){
if( list.get(2).equals(Something) )
return false;
else ... return true;
}
On this same System class I'm trying to use the method "work", giving it the List that I created on my Main class (myList).
public class System{
...
if( work(myList) ) //Don't know how to reffer to myList
return something;
Gives me the error "myList cannot be resolved to a variable".
So the problem is how to reffer to the list I made on my Main, named "myList".
Not sure if I explained that too well but any suggestions?
Make a List a property of System class, then pass it in the constructor
public class System {
private List<Images> images;
public System(List<Images> images) {
this.images = images;
}
//your other methods
}
Ah, in your main you should also pass the list:
System system = new System(myList);
Another option its to make myList public static and access it like this:
Main.myList
Declare one helper class and declare your list with setter and getters. Mainatin a singleton object of this class and use that list then in different other classes.
you need to make sure its accessible.
Right now your list is scoped the main() function. which is static to boot.
You need to make it accessible. You can do this by storing it in a static variable and having a static function return it.
Or you pass the main object along to other object, so they can access it.
public class Main {
private List<Images> myList = new ArrayList<Images>();
public static void main(String[] args) {
new Main(args);
}
public Main(String[] args) {
myList.add('foo.png');
myList.add('bar.png');
System mySystem = new System(this);
}
public List<Images> getImages() {
return myList();
}
}
public class System{
Main global;
public System(Main main) {
global = main;
}
public void doSomething() {
Iterator<Images> it = global.getImages().iterator();
while(it.hasNext()) {
Images images = it.next();
}
}
}

Categories

Resources