proxy an interface and call a default method

Jochen Theodorou blackdrag at gmx.org
Fri Jun 3 19:00:06 UTC 2016


That looks quite good to me

On 03.06.2016 11:51, Peter Levart wrote:
>
>
> On 06/02/2016 06:34 PM, forax at univ-mlv.fr wrote:
>>
>>     So perhaps, instead of providing a Proxy::findSuper method that
>>     returns a pre-bound MH, there could simply be a method like the
>>     following in the Proxy class:
>>
>>     public final Object invokeSuper(Class<?> interfaze, String
>>     methodName, MethodType methodType, Object ... args) { ... }
>>
>>     What do you think?
>>
>>
>> yes, good idea,
>> i think it should be static (and takes a Proxy as parameter) to avoid
>> unwanted overriding.
>
> Something like the following?
>
> http://cr.openjdk.java.net/~plevart/jdk9-dev/Proxy.invokeSuperDefaults/webrev.02/
>
> Usage is even simpler with this API:
>
> public class Test {
>
>      interface I1 {
>          default void m() {
>              System.out.println("default I1.m() called");
>          }
>      }
>
>      interface I2 {
>          default void m() {
>              System.out.println("default I2.m() called");
>          }
>      }
>
>      interface I12 extends I1, I2 {
>          @Override
>          void m();
>      }
>
>      public static void main(String[] args) {
>
>          InvocationHandler h = (proxy, method, params) -> {
>              System.out.println("InvocationHandler called for: " + method);
>              try {
>                  return Proxy.invokeSuper(proxy, method, params);
>              } catch (InvocationTargetException e) {
>                  throw e.getCause();
>              }
>          };
>
>          I1 i1 = (I1) Proxy.newProxyInstance(
>              I1.class.getClassLoader(), new Class<?>[]{I1.class}, h);
>          i1.m();
>
>          I2 i2 = (I2) Proxy.newProxyInstance(
>              I2.class.getClassLoader(), new Class<?>[]{I2.class}, h);
>          i2.m();
>
>          I12 i12 = (I12) Proxy.newProxyInstance(
>              I12.class.getClassLoader(), new Class<?>[]{I12.class}, h);
>          i12.m();
>      }
> }
>
>
> Gives the following output:
>
> InvocationHandler called for: public default void Test$I1.m()
> default I1.m() called
> InvocationHandler called for: public default void Test$I2.m()
> default I2.m() called
> InvocationHandler called for: public abstract void Test$I12.m()
> Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
>          at $Proxy2.m(Unknown Source)
>          at Test.main(Test.java:49)
> Caused by: java.lang.IllegalAccessException: no such method:
> Test$I12.m()void/invokeSpecial
>          at
> java.lang.invoke.MemberName.makeAccessException(java.base at 9-internal/MemberName.java:928)
>          at
> java.lang.invoke.MemberName$Factory.resolveOrFail(java.base at 9-internal/MemberName.java:1064)
>          at
> java.lang.invoke.MethodHandles$Lookup.resolveOrFail(java.base at 9-internal/MethodHandles.java:1692)
>          at
> java.lang.invoke.MethodHandles$Lookup.findSpecial(java.base at 9-internal/MethodHandles.java:1150)
>          at
> java.lang.reflect.Proxy.invokeSuper(java.base at 9-internal/Proxy.java:1151)
>          at Test.lambda$main$0(Test.java:33)
>          ... 2 more
> Caused by: java.lang.AbstractMethodError: Test$I12.m()V
>          at
> java.lang.invoke.MethodHandleNatives.resolve(java.base at 9-internal/Native
> Method)
>          at
> java.lang.invoke.MemberName$Factory.resolve(java.base at 9-internal/MemberName.java:1036)
>          at
> java.lang.invoke.MemberName$Factory.resolveOrFail(java.base at 9-internal/MemberName.java:1061)
>          ... 6 more
>
>
> ...which is expected. You can't call the super abstract method. You have
> to resolve the Method object of a particular interface (I1 or I2)
> yourself in such case.
>
> I think this is a simple API that everyone could understand.
>
> Regards, Peter
>


More information about the mlvm-dev mailing list