Java - 代理方法返回类型为Future时出现异常

时间:2015-12-23 02:19:02

标签: java reflection

我正在尝试Proxy,已实施InvocationHandler

public interface IDataInterface {
    public Future<String> getFuture();
}

public class MyData implements IDataInterface {
    private String data = "abc";

    @Override
    public Future<String> getFuture() {
        Callable<String> callMe = () -> {
            TimeUnit.SECONDS.sleep(5);
            return data;
        };
        FutureTask<String> task = new FutureTask<String>(callMe);
        task.run(); // must call run(), or it will block forever!
        return task;
    }
}

public class MyInvocationHandler implements InvocationHandler {
    private final Object delegate;
    private final ExecutorService scheduler;

    public MyInvocationHandler(Object obj) {
        this.delegate = obj;
        scheduler = Executors.newCachedThreadPool();
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.printf("[Proxy] Will call method: %s\n", method.getName());

        Object result = null;
        if(Future.class.isAssignableFrom(method.getReturnType())) {
            Callable<Object> methodRequest = () -> {
                Object res = method.invoke(delegate, args);
                return res;
            };
            Future<Object> future = scheduler.submit(methodRequest);
            scheduler.shutdown();
            result = future;
        } else {
            result = method.invoke(delegate, args);
        }
        // this will cause definite loop!
        // Object result = method.invoke(proxy, args);
        System.out.println("[Proxy] After method call.");
        return result;
    }
}

在main方法中,我运行:

IDataInterface myData = (IDataInterface)Proxy.newProxyInstance(
                                                        IDataInterface.class.getClassLoader(),
                                                        new Class<?>[] { IDataInterface.class },
                                                        new MyInvocationHandler(new MyData()));
        Future<String> future = myData.getFuture();
        try {
            System.out.println(future.get().toString());
        } catch(InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

得到以下异常java.util.concurrent.FutureTask cannot be cast to java.lang.String

[Proxy] Will call method: getFuture
[Proxy] Method return type is Future.
[Proxy] After method call.
Get data.Exception in thread "main" java.lang.ClassCastException: java.util.concurrent.FutureTask cannot be cast to java.lang.String
     at others.proxy.Main.main(Main.java:19)

根本原因是什么?

1 个答案:

答案 0 :(得分:1)

根本原因在于:

 if(Future.class.isAssignableFrom(method.getReturnType())) {
            Callable<Object> methodRequest = () -> {
                Object res = method.invoke(delegate, args);
                return res;
            };
            Future<Object> future = scheduler.submit(methodRequest);
            scheduler.shutdown();
            result = future;
        } 

Callable<Object> methodRequest (...)将返回FutureTask<String>

Future<Object> future = scheduler.submit(methodRequest)将返回Future<FutureTask<String>>

更改主要功能,您将看到

Future future = myData.getFuture();     
try {
    Future<String> future1 = (Future<String>) future.get(); 
    System.out.println(future1.get().toString());
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}