Non-virtual method invocation using reflection - java

In Java, when working with java.lang.reflect.Method how can I invoke a function without it being a virtual call?
I.e. I want this code to print "good" instead of what it currently does, which is print "bad":
Foo.java:
public class Foo {
public void doit() {
System.out.println("good");
}
}
Bar.java:
import java.lang.reflect.Method;
public class Bar extends Foo {
public void doit() {
System.out.println("bad");
}
public static void main(String[] args) throws Exception {
Bar b = new Bar();
/* Using Foo.class ought to do it right? */
Method m = Foo.class.getDeclaredMethod("doit", new Class[]{});
/* Surely if that didn't do it casting to Foo would? */
m.invoke((Foo)b, new Object[]{});
}
}
Nothing I do using reflection succeeds in printing "good".
My expectation was that using one or more of casting the first argument of invoke to Foo, and/or using Foo.class.getDeclaredMethod instead of Bar.class would be sufficient. Clearly I'm wrong about that, how can I get the desired behaviour still using reflection?

It seems the simplest solution is to use the java.lang.invoke package, which has a method called unreflectSpecial that simulates and invokespecial instruction:
import java.lang.reflect.Method;
import java.lang.invoke.*;
public class Bar extends Foo {
public void doit() {
System.out.println("bad");
}
public static void main(String[] args) throws Throwable {
Bar b = new Bar();
Method m = Foo.class.getDeclaredMethod("doit", new Class[]{});
MethodHandle h = MethodHandles.lookup().unreflectSpecial(m, Bar.class);
h.invoke(b);
}
}
Which does indeed print "good"

Related

Conditionally invoke method with same name from two different classes

I want an implementation where I need to invoke a method from one of two classes based on a condition. To illustrate, lets say I have two simplistic classes:
public class A implements IObject {
#Override
public void doIt() {
System.out.println("OBJECTA");
}
}
public class B implements IObject {
#Override
public void doIt() {
System.out.println("OBJECTB");
}
}
and an interface
public interface IObject {
void doIt();
}
My method to dynamically call a class function is implemented as:
void call(String s, A a, B b, Consumer<IObject> o) {
if(s.equalsIgnoreCase("CONDITION")) {
o.accept(a);
} else {
o.accept(b);
}
}
I can call the method as
A objectA = new A();
B objectB = new B();
call("CONDITION", objectA, objectB, IObject::doIt);
call("OTHER", objectA, objectB, IObject::doIt);
This will essentially invoke doIt on class A or B depending upon the condition parameter
Is there a cleaner way to achieve this by perhaps reducing the number of parameters an hence the function call signature?
Thanks
For my understanding of your problem:
You have a condition
You have a context to use (object a and b)
You would not ask such a question if there was not an intent to generalize your code for more than one condition or object (a, b). Otherwise, a ternary operator or a if would be far more easier to maintain (eg: ((condition) a:b).doIt() vs the code below).
Why not using a pattern like this:
A a = new A();
B b = new B();
String hint = ...;
List<Executor> list = new ArrayList<>();
list.add(new Executor("CONDITION"::equalsIgnoreCase, a::doIt));
list.add(new Executor(s -> true, b::doIt));
for (Executor executor : list) {
if (executor.process(hint)) {
break;
}
}
With Executor class:
class Executor {
private final Predicate<String> predicate;
private final Runnable runnable;
...
public boolean process(String s) {
if (!predicate.test(s)) {
return false;
}
runnable.run();
return true;
}
}
The loop will evaluate the condition, then run the code if true, otherwise continue onto the next element.
The Executor class is technically not bound to a or b; only the initial setup is.
Here is a complete different approach, utilizing java.lang.reflect.Proxy:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
*
* #author ben
*/
public class Test {
public interface IObject {
void doIt();
}
public static class A implements IObject {
#Override
public void doIt() {
System.out.println("OBJECTA");
}
}
public static class B implements IObject {
#Override
public void doIt() {
System.out.println("OBJECTB");
}
}
public static void main(String[] args) {
final boolean condition = true;
IObject proxyObj = (IObject)Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{IObject.class}, new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (condition)
new A().doIt();
else
new B().doIt();
return null;
}
});
proxyObj.doIt();
}
}
Here, you are creating a Proxy-Object for your Interface.
When you call .doIt() on this object, the invocation-handler will call the appropriate implementation, based on a condition.
You could then pass the proxy around and work with the invocation handler.
(It should be clear that this code should only give an idea and is only an example of how proxied interfaces/objects could be used to solve this problem.)
The above requirement can be implemented easily by using the 'Factory design pattern'
The factory design pattern involves these 3 steps:
Define the common interface for both the object types
Define the different classes that implement the common interface
Create a Factory class with a static method that returns one of the object types based on the input condition
Here is a working demo:
// File name: Demo.java
interface IObject {
public void doIT();
}
class A implements IObject {
public void doIT() {
System.out.println("DoIT - Class A");
}
}
class B implements IObject {
public void doIT() {
System.out.println("DoIT - Class B");
}
}
class IObjectFactory {
static IObject getObject(String CONDITION) {
if(CONDITION.equalsIgnoreCase("CONDITION")) {
return (new A());
}
return (new B());
}
}
public class Demo {
public static void main(String[] args) {
IObject io1 = IObjectFactory.getObject("condition");
IObject io2 = IObjectFactory.getObject("no condition");
io1.doIT();
io2.doIT();
}
}
Output:
> javac Demo.java
> java Demo
DoIT - Class A
DoIT - Class B
It really depends on your use cases. If the use cases are as simple as what you've described, you could remove the Consumer and just call doIt directly in the call function. However, I would recommend generalizing the function even further:
static <T> void ifElse(boolean decider, T optionA, T optionB, Consumer<T> callback) {
if (decider) {
callback.accept(optionA);
} else {
callback.accept(optionB);
}
}
Then call it with:
A a = new A();
B b = new B();
ifElse(condition.equals("CONDITION"), a, b, IObject::doIt);
Doing it this way is cleaner and more expandable. It also takes the same amount of code. (Untested, may have errors, but you get the idea). This approach is what you might see in purely ("purely") functional programming languages, where an if statement is just a function that takes a conditional and two functions (one for true, one for false).

java virtual method that does not return void

I want a method in a derived class to override a virtual method in a CONCRETE base class AND return something (i.e. not void) like this:
public class HelloWorldApp
{
public static void main(String args[])
{
Bar bar = new Bar();
bar.go();
}
}
public class Foo
{
public void go()
{
System.out.print(this.test().toString());
}
protected Integer test()
{
return 1;
}
}
public class Bar extends Foo
{
#Override
protected Integer test()
{
return 2;
}
}
Is there any way of doing this without the redundant 'return 1;' in Foo.test() which will never get run. It works fine obviously but it just seems like I'm doing something badly wrong.
This answer was created before the question was updated to state that the base class must be concrete.
If you expect Foo's test method never to be run, then enforce it by making the Foo class abstract, with test being abstract.
public abstract class Foo {
public void go() {
System.out.print(this.test().toString());
}
abstract protected Integer test();
}
If you cannot make Foo.test() abstract for some reason you didn't show in your example (for example because Foo extends a concrete class) and you are sure it will never be called, throwing a runtime exception may be preferable if there is no reasonable default value:
protected Integer test()
{
throw new UnsupportedOperationException("Calling test on Foo is not supported");
}
There are examples for this in the Java core APIs, see for example UnsupportedOperationException - this one has a slightly different meaning though, it is used for optional methods that some implementations of certain collection-types implement and some don't.

Mockito: how to use when(instance.meth).thenAnswer without mock

I have try following code:
package ro.ex;
/**
* Created by roroco on 11/11/14.
*/
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.mockito.Mockito.*;
public class ExTest extends junit.framework.TestCase {
class C {
public String m() {
return null;
}
}
public void testM() throws Exception {
when(new C().m()).thenAnswer(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
return (String) args[0];
}
});
}
}
i hope i can change a real instance meth not a mock, but above code raise:
when() requires an argument which has to be 'a method call on a mock'.
my question is: how to fix it.
I assume this is a sample code you created to ask a question here but in real, C should be the class under test (not a class within your test).
Class MyClassToTest {
public String m() {...}
}
Now in your test, mock class C. #Mock C c and followed by when(c.m()).thenAnswer..... in the test method.
Not sure why you would need that, but you can use spy:
public void testM() throws Exception {
C c = Mockito.spy(new C());
// actual method
c.m();
// stubbed method
when(c.m()).thenAnswer(...);
}
Alternatively, you can mock the object, and call thenCallRealMethod() when needed.

In Java 8, how do I make a method reference to a method that takes no parameters and returns void?

I have a bunch of methods with this signature:
public void sideEffects() {...}
public void foo() {...}
public void bar() {...}
(That is, they return void and take no parameters) And I'd like to be able to populate a List by doing something like this:
list.add(MyClass::sideEffects);
list.add(MyClass::foo);
list.add(MyClass::bar);
But, I'm unable to find a built in #FunctionalInterface in the java.util.function package that supports this signature. Will I have to create my own #FunctionalInterface for this?
In this case, java.lang.Runnable has the signature you're looking for and is a #FunctionalInterface. You can use this for this purpose, though I'm not sure if this is a good or bad practice.
The code will look like this:
package com.sandbox;
import java.util.ArrayList;
import java.util.List;
public class Sandbox {
public static void main(String[] args) {
List<Runnable> list = new ArrayList<>();
list.add(Sandbox::sideEffects);
list.add(Sandbox::foo);
list.add(Sandbox::bar);
for (Runnable runnable : list) {
runnable.run();
}
}
public static void sideEffects() {
System.out.println("sideEffects");
}
public static void foo() {
System.out.println("foo");
}
public static void bar() {
System.out.println("bar");
}
}

InstantiationException on newInstance of generated anonymous class

Update: this is more-or-less a dupe, and it turns out to be compiler magic adding a constructor to pass in the local variable in build2.
Given an interface like such:
public interface IFoo {
public int get();
}
The code below prints 1, 1, 2 and then throws an exception when trying to call getClass().newInstance() on the value returned by build2, but does not when calling the same on the returned value of build1. Any ideas why?
public class Foo {
public static IFoo build1() {
return new IFoo() { public int get() { return 1; } };
}
public static IFoo build2(final int v) {
return new IFoo() { public int get() {return v;} };
}
public static void main(String[] args) throws Exception {
IFoo foo, bar;
foo = build1();
System.out.println(foo.get());
bar = foo.getClass().newInstance();
System.out.println(bar.get());
foo = build2(2);
System.out.println(foo.get());
bar = foo.getClass().newInstance();
System.out.println(bar.get());
}
}
My debugger indicates that in the newInstance() call, getConstructor0 is throwing a NoSuchMethodException.
Here's what happens:
newInstance() requires a nullary constructor
when you create an anonymous class that is accessing a final variable, a field is actually implicitly created to hold this value, which is initially passed to its implicit constructor
thus, the IFoo created in build2 does NOT actually have a nullary constructor
Here's a snippet to show what's going on:
import java.lang.reflect.*;
public class Foo {
interface IFoo { public int get(); }
public static IFoo build2(final int v) {
return new IFoo() { public int get() {return v;} };
}
public static void main(String[] args) throws Exception {
Class<?> klazz = build2(42).getClass();
for (Constructor<?> c : klazz.getDeclaredConstructors()) {
System.out.println(c);
}
// prints: Foo$1(int)
}
}
It shows that Foo$1 (the assigned binary name for the anonymous IFoo class) has only one constructor, and it takes an int. This is how it can return v, because what's returned is actually whatever is assigned to the implicitly created field by this implicitly created constructor.
It is instructive to decompile the Foo$1 (using e.g. javap -c) to see what bytecode gets generated. You will see that in fact this is what happens when a final variable is accessed by an anonymous class.
Related questions
Why am I having this InstantiationException in Java when accessing final local variables?

Categories

Resources