I am reading Java 8 book, and it comes with a sample I reproduce:
#FunctionalInterface
public interface Action {
public void perform();
}
An Implementor:
public final class ActionImpl implements Action {
public ActionImpl() {
System.out.println("constructor[ActionIMPL]");
}
#Override
public void perform() {
System.out.println("perform method is called..");
}
}
A caller:
public final class MethodReferences {
private final Action action;
public MethodReferences(Action action) {
this.action = action;
}
public void execute() {
System.out.println("execute->called");
action.perform();
System.out.println("execute->exist");
}
public static void main(String[] args) {
MethodReferences clazz = new MethodReferences(new ActionImpl());
clazz.execute();
}
}
If this is called the following is print into the output:
constructor[ActionIMPL]
execute->called
perform method is called..
execute->exist
Everything is all right but if I use method references not perform message method is printed! Why is this, am I missing something?
If I use this code:
MethodReferences clazz = new MethodReferences(() -> new ActionImpl());
clazz.execute();
Or this code:
final MethodReferences clazz = new MethodReferences(ActionImpl::new);
This is printed:
execute->called
constructor[ActionIMPL]
execute->exist
No exception message or anything else is printed. I am using Java 8 1.8.25 64bit.
Update
For readers that are studying like me, this is the right running code.
I have created a class the caller.
Because I need to implement a empty method "perform from the Action functional interface" which I need to pass as parameter to class constructor MethodReference I reference the "constructor of the MethodReferenceCall which is a empty constructor" and I can use it.
public class MethodReferenceCall {
public MethodReferenceCall() {
System.out.println("MethodReferenceCall class constructor called");
}
public static void main(String[] args) {
MethodReferenceCall clazz = new MethodReferenceCall();
MethodReferences constructorCaller = new MethodReferences(MethodReferenceCall::new);
constructorCaller.execute();
}
}
This
MethodReferences clazz = new MethodReferences(() -> new ActionImpl());
does not use method reference, it uses a lambda expression. The functional interface is Action's
public void perform();
So
() -> new ActionImpl()
gets translated into something similar to
new Action() {
public void perform() {
new ActionImpl();
}
}
Similarly, in
MethodReferences clazz = new MethodReferences(ActionImpl::new);
the ActionImpl::new, which does use a constructor reference, is translated into something like
new Action() {
public void perform() {
new ActionImpl();
}
}
This ActionImpl::new does not invoke new ActionImpl(). It resolves to an instance of the expected type whose functional interface method is implemented as invoking that constructor.
Related
This is my test code:
Activity activityMock = Mockito.mock(TestActivity.class);
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
Object[] args = invocationOnMock.getArguments(); // ->>>> args contains one Foo instance called "foo"
return invocationOnMock;
}
}).when(activityMock).runOnUiThread(any(Runnable.class));
runDialogOnUiThread(activityMock, new Foo());
To the following production code:
public static void runDialogOnUIThread(final Activity activity, final Foo foo) {
activity.runOnUiThread(new Runnable() {
#Override public void run() {
doSmth();
}
});
}
See my comment in the test code. I expect invocationOnMock.getArguments() to return the Runnable instance, but it is returning the Foo instance (Which makes absolutely no sense to me)?
I thought
doAnswer(new Answer(){..}).when(b).bMethod(any(C.class))
intercepts when bMethod() is called anywhere on b and it will pass the instance of C.class to the doAnswer() to make it available in the "new Answer().."-Callback..
How can I access the anonymous Runnable instance, which is created in the production code?
I'm guessing that your anonymous Runnable instance is defined in Foo, right?
Here's some code I wrote to try to reproduce your issue:
public class MockitoTest {
#Test
public void test() {
final Activity activityMock = Mockito.mock(TestActivity.class);
doAnswer(new Answer() {
#Override
public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
final Object[] args = invocationOnMock.getArguments();
System.out.println("Is argument a Runnable? " + (args[0] instanceof Runnable));
System.out.println("What is the argument toString()? " + args[0].toString());
return invocationOnMock;
}
}).when(activityMock).runOnUiThread(any(Runnable.class));
runDialogOnUIThread(activityMock);
}
public void runDialogOnUIThread(final Activity activity) {
final Runnable r = new Runnable() {
#Override public void run() {
System.out.println("***");
}};
activity.runOnUiThread(r);
}
public static interface Activity {
void runOnUiThread(Runnable r);
}
public static class TestActivity implements Activity {
#Override
public void runOnUiThread(final Runnable r) { r.run(); }
}
}
Pretty much the same thing, but it is trimmed down to illustrate where I think you are getting confused.
The output is:
Is argument a Runnable? true
What is the argument toString()? stackoverflow.MockitoTest$2#6b143ee9
Note that the second output contains MockitoTest for the toString() output and nothing about it being a Runnable. That's because the toString() method is not being explicitly defined in the anonymous Runnable.
Let's change the Runnable as follows:
final Runnable r = new Runnable() {
#Override public void run() {
System.out.println("***");
}
#Override public String toString() {
return "ANON RUNNABLE";
}
};
Then the output is:
Is argument a Runnable? true
What is the argument toString()? ANON RUNNABLE
What I suspect you were getting tripped up on is that the toString() output looked like the same class name as the class that the anonymous Runnable was created in.
I have an 3rd party API call which returns the following object:
public class A {
protected void common() {
System.out.println("common is called in A");
}
public void test1() {
common();
System.out.println("test1 is called in A");
}
public void test2() {
common();
System.out.println("test2 is called in A");
}
}
But I'd like to modify its behavior like the following ModifiedA shows:
public class ModifiedA extends A {
#Override
protected void common() {
super.common();
System.out.println("common is called in ModifiedA");
}
}
So what I am trying to do is:
A a = 3rdPartyAPI_call();
//
// Now I'd like to get a ModifiedA which has changed common() behavior.
//
How to use javassist/CGLIB to accomplish this ?
One easy way may be to like this:
public class ModifiedA extends A {
private A a;
public ModifiedA(final A a) {
this.a = a;
}
//
// Override every public method in A
//
#Override
protected void common() {
super.common();
System.out.println("common is called in ModifiedA");
}
}
But since A's definition comes from 3rd party and is very complex and may change, so I'd like to use a proxy to do this?
Thanks for your comments in adavance.
You can use CGLib to implement a delegator pattern without having to override all the methods. There are a few different approaches to implement this depending on style but here is one similar to your example.
You can wrap the instance using a cglib Enhancer:
public static <T> T wrapInstance(final T original) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(original.getClass());
enhancer.setCallback(new MethodInterceptor() {
#Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object returnValue = proxy.invoke(original, args);
if (method.getName().equals("common")) {
System.out.println("common is called");
}
return returnValue;
}
});
return (T) enhancer.create();
}
eclps post will fullfill your requirement and it works.I want to add some more code to eclps code.
Adding filter which give index zero for common method and rest all method to One. MethodInterceptor callback will intercept only common method and rest all method use NoOp intercetor(which will call super class apis).This way filtering is not happening for every method call.
public static <T> T wrapInstance(final T original) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(original.getClass());
enhancer.setCallbackFilter(new CallbackFilter() {
#Override
public int accept(Method method) {
if (method.getName().equals("common")) {
return 0;
}
return 1;
}
});
enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
#Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// only common method will intercept this call back.
return proxy.invoke(this, args);
}
}, NoOp.INSTANCE});
return (T) enhancer.create();
}
i'm trying to write anonymous inner class
interface Face{
void seeThis(String what);
}
class Eyes {
public void show(Face f){}
}
public class Seen {
public void test() {
Eyes e = new Eyes();
e.show(new Face() {
#Override
public void seeThis(String what){
System.out.print(what);
}
});
public static void main(String[] args) {
Seen s = new Seen();
s.test();
}
}
How to call seeThis() and how to pass parameter to it?
Method seeThis() belongs to Face class, which instance is anonymous and thus cannot be reached without storing reference to it. If you want to store a reference, you can do this in the following way:
public class Seen {
public Face face;
....
this.face = new Face() { ... };
e.show(this.face);
And then,
Seen s = new Seen();
s.face.seeThis();
Now, regarding passing the parameter. You have two options - declare parameter outside of anonymous class and make it final in order to be reachable by this anonymous class, or replace anonymous class with normal one and pass the parameter to its constructor:
Approach one:
final int parameter = 5;
...(new Face() {
#Override
public void seeThis() {
System.out.println(parameter);
}
});
Approach two:
public class MyFace implements Face() {
private final int parameter;
public MyFace(int parameter) {
this.parameter = parameter;
}
#Override
public void seeThis() {
System.out.println(parameter);
}
}
Then,
...
e.show(new MyFace(10));
I have a class with some constructors like this:
public MyClass(Control caller, WritableList elements, String pattern) {
this(caller, elements, pattern, new LabelProvider());
}
public MyClass(Control caller, WritableList elements, String pattern, ILabelProvider labelProvider) {
super(caller.getShell(), labelProvider);
// ...
}
public MyClass(Control caller, Collection<String> elements, String pattern) {
super(caller.getShell(), new LabelProvider());
// ...
}
If I try to create an instance of it using this:
new MyClass(getControl(), getWritableList(), "test");
or this:
new MyClass(getControl(), (WritableList) getWritableList(), "test");
Eclipse is complaining that the constructor is ambiguous. If I do this however:
new MyClass(getControl(), (Collection<SomeType>) getWritableList(), "test");
everything is fine. I was wondering what could be the problem? I'm using org.eclipse.core.databinding.observable.list.WritableList which comes with the RCP framework.
Edit:
I thought that WritableList extending the Collection interface could be the error but I created some test classes and it turned out that it is not the case:
public class Main {
/**
* Main.
* #param args
*/
public static void main(String[] args) {
TestClass obj = new TestClass(getTypeAInstance(), "asd");
}
public static SomeTypeA getTypeAInstance() {
return new SomeTypeA();
}
public static interface SomeInterface<T> {
}
#SuppressWarnings("rawtypes")
public static interface SomeInterfaceExtensionWithoutTypeParam extends SomeInterface {
}
public static interface SomeInterfaceExtensionWithTypeParam<T> extends SomeInterface<T> {
}
#SuppressWarnings("rawtypes")
public static interface SomeIntermediateInterface extends SomeInterfaceExtensionWithoutTypeParam, SomeInterfaceExtensionWithTypeParam {
}
public static class SomeTypeA implements SomeIntermediateInterface {
}
public static class TestClass {
public TestClass(SomeInterface<String> i, String s) {
}
public TestClass(SomeTypeA a, String s) {
}
}
}
It seems that the problem was with Eclipse's own Java compiler.
I would like to know how to create a contract with the caller for the Method parameter in the event the method has parameters itself. So that I use...
ClassA {
String string_ = "HI";
public static void subscribe(Object class, Method action) {
action.invoke(class, string_);
}
}
ClassB {
ClassB() {
ClassA.subscribe(this, this.getClass().getMethod("load", String.class));
}
public void load(String input) {
if(input.equals("HI")) {
...
}
}
}
I would like to know how to ensure the Method passed as "action" takes String as a parameter (i.e. ensure Method action == load(String){})? Is there something like this available:
public static void subscribe(Object class, Method action(String.class)) {
I want to do it in the method signature of subscribe so that it is obvious to the calling class (ClassB) that it needs to be prepared to take an argument of specified type.
EDIT: Updated last code bit so not to appear as if Method was generic. Poor choice of using <> on my part to represent an example of what I was trying to convey.
There's no way to do that in Java. The Method class is not generic, and there is no way for it to be so, because methods can take any number of parameters, and there is no way to make a class generic over a variable number of types.
Probably the best you can do is to declare your own type to use instead of Method:
public interface Action<T, P> {
public void invoke(T target, P parameter);
}
Then:
public static <T> void subscribe(T obj, Action<T, String> action) {
action.invoke(obj, string_);
}
ClassB() {
ClassA.subscribe(this, new Action<ClassB, String>() {
public void invoke(ClassB target, String parameter) {
target.load(parameter);
}
});
}
In C# there are means to achieve what you are trying to do but I can't think of a way to ensure that at compile time for java.
can you resort to using intefaces?
interface ILoader{
void load(String input);
}
ClassA {
String string_ = "HI";
public static void subscribe(ILoader loader) {
loader.load( string_);
}
}
ClassB implements ILoader {
ClassB() {
ClassA.subscribe(this);
}
public void load(String input) {
if(input.equals("HI")) {
...
}
}
}
Couldn't you use a slight modification of the Command Pattern?
puclic interface LoadCommand {
public load(String input);
}
public class ClassB implements LoadCommand {
public load(String input) {
// do stuff here
}
}
public class ClassA {
String myInput = "HI";
public static void subscribe(LoadCommand command) {
command.load(myInput)
}
}
The load method in the LoadCommand interface takes one String argument.