Understanding "proxy" arguments of the invoke method of java.lang.reflect.InvocationHandler

StackOverflow https://stackoverflow.com/questions/22930195

  •  29-06-2023
  •  | 
  •  

Question

I would like to understand the purpose of the proxy argument of the invoke method of java.lang.reflect.InvocationHandler.

  • How and when should it be used?
  • What is its runtime-type?
  • Why not use this instead?
Was it helpful?

Solution

There's in fact little you can do with the actual proxy. Nevertheless it's part of the invocation context, and you can use it to gain information on the proxy using reflection, or use it in subsequent calls (when calling another method with that proxy, or as a result.

Example: an acccount class, which allows to deposit money, whose deposit() method returns the instance again to allow method chaining:

private interface Account {
    public Account deposit (double value);
    public double getBalance ();
}

Handler:

private class ExampleInvocationHandler implements InvocationHandler {

    private double balance;

    @Override
    public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {

        // simplified method checks, would need to check the parameter count and types too
        if ("deposit".equals(method.getName())) {
            Double value = (Double) args[0];
            System.out.println("deposit: " + value);
            balance += value;
            return proxy; // here we use the proxy to return 'this'
        }
        if ("getBalance".equals(method.getName())) {
            return balance;
        }
        return null;
    }
}

And an example of its usage:

Account account = (Account) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {Account.class, Serializable.class},
    new ExampleInvocationHandler());

// method chaining for the win!
account.deposit(5000).deposit(4000).deposit(-2500);
System.out.println("Balance: " + account.getBalance());

As for your second question: the runtime type can be evaluated using reflection:

for (Class<?> interfaceType : account.getClass().getInterfaces()) {
    System.out.println("- " + interfaceType);
}

And your third question: 'this' would refer to the invocation handler itself, not the proxy.

OTHER TIPS

To complement Peter's answer. I added the following line regarding the runtime-type of the proxy:

System.out.println("accountGetClass() : " + account.getClass());

Which outputs:

accountGetClass() : class com.sun.proxy.$Proxy0
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top