首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何以反射方式调用Java 8默认方法

如何以反射方式调用Java 8默认方法
EN

Stack Overflow用户
提问于 2014-03-25 00:11:59
回答 5查看 7.7K关注 0票数 16

给出这个简单的"Hello World“式Java 8接口,如何通过反射调用它的hello()方法?

代码语言:javascript
复制
public interface Hello {
    default String hello() {
        return "Hello";
    }
}
EN

回答 5

Stack Overflow用户

发布于 2014-06-02 17:03:36

为此,您可以使用MethodHandles

代码语言:javascript
复制
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ReflectiveDefaultMethodCallExample {

    static interface Hello {
        default String hello() {
            return "Hello";
        }
    }

    public static void main(String[] args) throws Throwable{

        Hello target =
                //new Hello(){};
                (Hello)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{Hello.class}, (Object proxy, Method method, Object[] arguments) -> null);
        Method method = Hello.class.getMethod("hello");

        Object result = MethodHandles.lookup()
                                     .in(method.getDeclaringClass())
                                     .unreflectSpecial(method,method.getDeclaringClass())
                                     .bindTo(target)
                                     .invokeWithArguments();
        System.out.println(result); //Hello
    }
}
票数 16
EN

Stack Overflow用户

发布于 2018-03-28 18:47:32

不幸的是,似乎没有一个理想的解决方案可以在所有JDK 8、9、10上工作,它们的行为方式是不同的。I've run into issues when fixing an issue in jOORI've also blogged about the correct solution here in detail

此方法适用于Java 8

在Java8中,理想的方法是使用黑客从Lookup访问包私有构造函数

代码语言:javascript
复制
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;

interface Duck {
    default void quack() {
        System.out.println("Quack");
    }
}

public class ProxyDemo {
    public static void main(String[] a) {
        Duck duck = (Duck) Proxy.newProxyInstance(
            Thread.currentThread().getContextClassLoader(),
            new Class[] { Duck.class },
            (proxy, method, args) -> {
                Constructor<Lookup> constructor = Lookup.class
                    .getDeclaredConstructor(Class.class);
                constructor.setAccessible(true);
                constructor.newInstance(Duck.class)
                    .in(Duck.class)
                    .unreflectSpecial(method, Duck.class)
                    .bindTo(proxy)
                    .invokeWithArguments();
                return null;
            }
        );

        duck.quack();
    }
}

这是同时适用于私有可访问接口和私有不可访问接口的唯一方法。然而,上面的方法对JDK内部的反射访问是非法的,这在未来的JDK版本中将不再有效,或者如果在JVM上指定了--illegal-access=deny

此方法适用于Java 9和10,但不适用于8

代码语言:javascript
复制
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Proxy;

interface Duck {
    default void quack() {
        System.out.println("Quack");
    }
}

public class ProxyDemo {
    public static void main(String[] a) {
        Duck duck = (Duck) Proxy.newProxyInstance(
            Thread.currentThread().getContextClassLoader(),
            new Class[] { Duck.class },
            (proxy, method, args) -> {
                MethodHandles.lookup()
                    .findSpecial( 
                         Duck.class, 
                         "quack",  
                         MethodType.methodType(void.class, new Class[0]),  
                         Duck.class)
                    .bindTo(proxy)
                    .invokeWithArguments();
                return null;
            }
        );

        duck.quack();
    }
}

解决方案

只需实现上述两种解决方案,并检查您的代码是否在JDK 8或更高版本的JDK上运行,就可以了。直到您不再是这样:)

票数 15
EN

Stack Overflow用户

发布于 2014-03-25 00:15:03

你不能直接调用它,因为你需要一个实现类的实例。为此,您需要一个实现类。default方法不是static方法,您也不能创建接口的实例。

因此,假设您有一个实现类:

代码语言:javascript
复制
class HelloImpl implements Hello {  }

您可以像这样调用该方法:

代码语言:javascript
复制
Class<HelloImpl> clazz = HelloImpl.class;
Method method = clazz.getMethod("hello");
System.out.println(method.invoke(new HelloImpl()));  // Prints "Hello"
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22614746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档