Can I pass a method into another method in Java - java

For example I have the following method call:
Requests.sendGet("/type", Model.setTypes);
Model.setTypes is a setter for a List of Types, I want the sendGet method to be able to call whatever method gets passed into it, and no the sendGet method can't just call Model.setTypes itself, because it depends on what type of Get request is being performed.
Thanks to anyone who replies.

Use the command pattern.
public interface Command {
public void execute();
}
public class Requests {
public static void sendGet(String url, Command command) {
// Do your stuff here and then execute the command.
command.execute();
}
}
final Model model = getItSomehow(); // Must be declared final.
Requests.sendGet("/type", new Command() {
public void execute() {
model.setType();
}
});
You can if necessary add an argument to execute() method, like RequestEvent which can be created by Requests#sendGet() and accessed in Command#execute().

It is possible, although clumsy: You can use java.lang.reflect.Method to point to a method and call its invoke member to call it.
However, in almost all cases, this is not what you want to do. Instead, use an interface for that (i.e. your function accepts an object of a certain type that implements an interface), or you can take a Runnable and call the run() function of it, or a Callable and use call().
(Thanks to Crom for pointing out Callable)

Java does not have first class functions: that is functions - amongst other things - passable as arguments - albeit there is a proposal. Instead this problem is typically solved in Java with function objects - usually objects that implement an interface with a single function. An example would be the Collections API Comparator.
So in your situation define an interface (e.g. ModelSetter) with a single method (e.g. setTypes(List list)). Define Request.sentGet(ModelSetter modelSetter).

public void invokeAMethod(Object o, String methodName, String...params){
try{
Class<?> driverClass = o.getClass();
Method[] driverMethod = driverClass.getMethods();
for(Method m : driverMethod) {
if(m.getName().equalsIgnoreCase(methodName)) {
if(m.isVarArgs()) {
Object[] obj = new Object[params.length];
for(int i=0;i<params.length;i++) {
obj[i] = params[i];
}
m.invoke(new Object[]{obj});
}
else
m.invoke(o,params);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
In The above code, parameters are:
Object o: Object of the class in which your calling method belongs
String methodName: name of the method which you want to call.
String...params: parameters of the method which you want to call.
public class Sample{
public static void main(String[] args){
method2("method1")
}
public void method1(){
System.out.println("method1");
}
public static void method2(String methodName){
invokeAMethod(this,method1);
}
}

Related

Lambda body isn’t executed unless corresponding method is invoked

I am learning about Java Lambdas and I asked myself is it always required to call a abstract method of functional interface if I want to use the lambda here?
#FunctionalInterface
public interface A {
public void somefunction();
}
#FunctionalInterface
public interface B extends A {
}
public class testing {
public static void main(String[] args) {
B b = () -> System.out.println("MyText");
b.somefunction(); //Why do I need to call somefunction()
}
}
If I don't write b.somefunction(); I don't get any output even though the compiler does not give an error.
I don't pass any value to the method so why do I need to call the abstract method?
Is there anyway to skip the abstract method call? If my case was to add or perform some calculations, then I can understand that I need to pass some values in method, but in the above scenario I am just printing the value.
If you want the output to print when your program runs, write:
public class testing {
public static void main(String[] args) {
System.out.println("MyText");
}
}
If you want the output to print when some other function runs, then you might use a lambda:
class Testing {
public static void main(String[] args) {
runn(() -> System.out.println("MyText"), 10);
}
static runn(Runnable task, int times) {
for (int i = 0; i < times; ++i) {
task.run();
}
}
}
Lambdas exist to make it easy to specify a function whose execution you want to delegate to another entity. When the lambda is invoked, its arguments, and the treatment of its result are up to someone else.
A functional interface serves to provide a way
to define what is to be performed on a given call and
to define when it is to be called.
Normally, you'd define a "lambda object" as you did and then pass it to somewhere else to tell what to do under a certain circumstance. If you want to see it this way, it is a kind of callback.
The entity where you pass this object calls/uses it when it sees time to do so, or you do it yourself, as you do it in your example.

How to use consumer and supplier instead Reflection in java 8

I have a two simple class and use reflection pattern for invoke method.
I want to write module programming.
Suppose we have a table in database that keep modules name:
Id moduleName methodName ClassName active
1 sample a com.examle.sample true
2 SMS sendSMS com.example.SMS false
3 Email sendEmail com.example.Email false
... ... ... ...
When active is true the module must be activated.So when i write a program and compile that, i do not like again compile whole MyApp. So i use reflection pattern to invoke module. please see the codes.
public class Sample {
public void a() {
System.out.println("Call Method a");
}
}
public class SMS {
public void sendSMS(String str) {
System.out.println("send SMS ok");
}
}
public class Email {
public void sendEmail(String str) {
System.out.println("send Email ok");
}
}
public class SampleMainClass {
public static void main(String[] args) {
//coonect to database and fetch all record in tables
while(record.next){
if (record.getActive()){
Object o = Class.forName(record.getClssName()).newInstance() ;
Method method = o.getClass().getDeclaredMethod(record.getMethodName());
method.invoke(o);
}
}
}
output
Call Method a
So i heard in the java 8, reflection pattern is deprecate and instead that we can use consumer and supplier.
How to use consumer and supplier instead Reflection in java 8?
Thanks.
public class Q42339586 {
static class Sample {
void a() { System.out.println("a() called"); }
void b() { System.out.println("b() called"); }
}
static <T> void createInstanceAndCallMethod(
Supplier<T> instanceSupplier, Consumer<T> methodCaller) {
T o = instanceSupplier.get();
methodCaller.accept(o);
}
public static void main(String[] args) {
createInstanceAndCallMethodJava8(Sample::new, Sample::a);
}
}
Here, createInstanceAndCallMethod does what is done in your main() Method but it accepts parameters instead.
A Supplier is used to create a new instance and a Consumer is used to call a particular method on that instance. In the example both method references are passed as both parameters. Instead, you could also use lambda expressions and write () -> new Sample() and o -> o.a() instead. Please refer to this official tutorial part for more information.
The advantages over reflection are obvious:
You cannot ask createInstanceAndCallMethod to create an instance of a class that doesn't exist.
You cannot ask createInstanceAndCallMethod to call a method that doesn't exist in a particular class.
As a result of both you don't have to deal with any checked Exception.
Of course this does only work when at some place in the code the actual class and method are known, e.g. it's not possible to read class and method name from a properties file and then use Java 8 mechanisms to safely create an instance and call a particular method.
Consumer and Supplier are functional interfaces and they do not refer to reflection.
It's different things.
So i heard in the java 8, reflection pattern is deprecate and instead that we can use consumer and supplier.
Wrong information.

Check is instance method is called from a constructor

I would like to check, from an instance method of a non-final class, whether the constructors and initializers of that class and its chain of subclasses for the specific instance have already completed.
In the following example, I have a class Abstract, which can be used to implement an interface which allows listeners to be added (which, for simplicity, are just Runnable instances here) and which provides a method signalEvent() which calls all attached listeners.
abstract class Abstract {
protected final void signalEvent() {
// Check that constructs have run and call listeners.
}
public final void addListener(Runnable runnable) {
...
}
}
class Concrete extends Abstract {
Concrete() {
// Should not call signalEvent() here.
}
void somethingHappened() {
// May call signalEvent() here.
}
}
Now it is possible to call signalEvent() from within the subclass constructor, but there is no way that a listener has already been added by that time and the event would just be lost. In our code-base, once in a while, someone adds such a call and I would like to be able to catch such calls as early as possible (using an assert statement or similar).
Is it possible to check whether an instance method is being called, directly or indirectly, from the subclass constructor or initializer of the current instance or, alternatively, is it possible to check whether all constructors for an instance have been completed?
In short, there is no elegant Java mechanism that allows you to do that, but you may consider using a factory pattern. Instead of creating instances directly using new keyword, you could create a factory class, that takes care of creating the actual instance and invokes an additional "post-create" method, that lets the instance know it's been completely created.
If you're using some dependency injection like spring, you get that out of the box, but if not, a solution could look something like this:
interface PostConstruct { // the classes need to implement that
void postConstruct();
}
public class InstanceFactory {
public <T extends PostConstruct> T create(Class<T> clazz, Object... params) {
T instance = //create using reflection
instance.postConstruct();
return instance;
}
}
A solution to the problem to see if a method or code is being called from a constructor. The code below will print true and false respectivly but would be slow and not pretty at all.
I still believe it is not the right solution for the problem above. As Codbender said, better to check if a listener has been added or set a status variable which would be faster
Edit - fixed the issue that Codebender mentioned and also made sure to check back in the stack trace incase of being called a couple of methods deep
public class TestClass extends TestAbstract {
public TestClass() throws Exception {
submethod();
}
public void submethod() throws Exception {
System.out.println(isInConstructor());
}
public static void main(String[] args) throws Exception {
System.out.println(new TestClass().isInConstructor());
}
}
public class TestAbstract {
public boolean isInConstructor() throws Exception {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement element : elements) {
if (element.getMethodName().equals("<init>") &&
TestAbstract.class.isAssignableFrom(Class.forName(element.getClassName()))) {
return true;
}
}
return false;
}
}

Using different method depending on class in Java

I'm trying to reduce some code duplication. Currently i got two methods that are almost identical, the major difference being calling two separate methods within them.
Below is basically what i wanna do:
private void combinedMethod(StandardClass sc, MyClass mc)
{
Method m = null;
if(mc instanceof MySubClass1)
m = sc.RelevantFor1();
if(mc instanceof MySubClass2)
m = sc.RelevantFor2();
m(mc.getA(), mc.getB());
}
I've tested (and it works) this using reflection. But is there a better way of doing it? I read somewhere that reflection is slow and only to be used as a last resort. Is it in this case?
Also in this case the StandardClass is a standard class in the java api. The Class I send in is of my own making.
It isn't clear how exactly those methods look like, or what they are doing, but it seems like a perfect polymorphism case. You can create a method in super class - MyClass I suppose in this case. And override those methods in your subclasses.
Now, when you call that method on MyClass reference, appropriate subclass method will be called based on actual instance. Now invoke whatever method you want to invoke in respective overridden methods.
Somewhere along the lines of:
class MyClass {
public void method(StandardClass sc) { }
}
class MySubClass1 extends MyClass {
public void method(StandardClass sc) {
sc.method(getA(), getB());
}
}
class MySubClass2 extends MyClass {
public void method(StandardClass sc) {
sc.anotherMethod(getA(), getB());
}
}
And then your combinedMethod looks like:
private void combinedMethod(StandardClass sc, MyClass c) {
c.method(sc);
}

Abstracting initialization

I have some classes that I want to initialize only if the passed parameter is true.
It turns out that every implementaion of this method is the same, but is just used for a different class.
public static NamedScene getScene(boolean init) {
if (mainMenu == null) {
mainMenu = new MainMenu();
}
if (init) mainMenu.init();
return mainMenu;
}
I would like to abstract this method, so I won't have to access it manually via calling MainMenu.init(true); but with scene.init(true); where scene extends the abstract class.
There are some default properties for every class, like name that is acessed via the abstract method getName(). I expect the method to sometimes return the class instance without init(), and sometimes with init().
Consider using a generic method for this.
It's not the exact code you wanted, but you will understand from it:
public static <T> T conditionalInit(Class<T> clazz, boolean okToInit) {
try {
return okToInit?clazz.newInstance() : null;
} catch (Exception e) {
return null;
}
}
Usage:
Person p = conditionalInit(Person.class, true); //not null
Person p2 = conditionalInit(Person.class, false); //null
Comments:
1. If you must execute an "init" method, I suggest all your classes implement an Initializable interface which will contain an "init" method.
And then the signature of the method will be:
public static T conditionalInit(Class clazz, boolean okToInit)
2. I remind you that a static generic method can exist in a non generic class.

Categories