wlbc123456789 2021-07-23 15:53 采纳率: 0%
浏览 125

动态代理中的调用处理器接口(InvocationHandler)invoke方法的参数args为啥不能传递自定义类对象

正在学习core java的第六章中的proxy这一小节,感觉非常有意思,下面是书中举例的代码

package proxy;

import java.lang.reflect.*;
import java.util.*;

public class ProxyTest
{
   public static void main(String[] args)
   {
      Object[] elements = new Object[1000];

      // fill elements with proxies for the integers 1 ... 1000
      for (int i = 0; i < elements.length; i++)
      {
         Integer value = i + 1;
         InvocationHandler handler = new TraceHandler(value);
         Object proxy = Proxy.newProxyInstance(null, new Class[] { Comparable.class } , handler);
         elements[i] = proxy;
      }

      // construct a random integer
      Integer key = new Random().nextInt(elements.length) + 1;

      // search for the key
      int result = Arrays.binarySearch(elements, key);

      // print match if found
      if (result >= 0) System.out.println(elements[result]);
   }
}

/**
 * An invocation handler that prints out the method name and parameters, then
 * invokes the original method
 */
class TraceHandler implements InvocationHandler
{
   private Object target;

   /**
    * Constructs a TraceHandler
    * @param t the implicit parameter of the method call
    */
   public TraceHandler(Object t)
   {
      target = t;
   }

   public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
   {
      // print implicit argument
      System.out.print(target);
      // print method name
      System.out.print("." + m.getName() + "(");
      // print explicit arguments
      if (args != null)
      {
         for (int i = 0; i < args.length; i++)
         {
            System.out.print(args[i]);
            if (i < args.length - 1) System.out.print(", ");
         }
      }
      System.out.println(")");

      // invoke actual method
      return m.invoke(target, args);
   }
}

我测试了代码后,突然想到如果不用包装类Integer,直接用自定义类,然后实现接口Comparable,能不能也可以用二分查找函数来实现代理调用,下面是我的代码。

package wwydr.chapter6;/*

import java.lang.reflect.*;
import java.util.*;


public class ProxyTest
{
    public static void main(String[] args)
    {
        Object[] elements = new Object[1000];

        // fill elements with proxies for the integers 1 ... 1000
        for (int i = 0; i < elements.length; i++)
        {
//            Integer value = i + 1;
            int rAge = new Random().nextInt(65) + 1;
            Comparable value = new Employee32(rAge);
            InvocationHandler handler = new TraceHandler(value);
            ClassLoader loader=value.getClass().getClassLoader();
            Class [] interfaces=value.getClass().getInterfaces();
            Object proxy = Proxy.newProxyInstance(loader, interfaces , handler);
            elements[i] = proxy;
        }

        // construct a random integer
        Integer key = new Random().nextInt(65) + 1;

        // search for the key
        //binarySearch函数的返回值:
        // 如果key在数组中,则返回搜索值的索引;否则返回-1或者”-“(插入点)。插入点是索引键将要插入数组的那一点,即第一个大于该键的元素索引。
        int result = Arrays.binarySearch(elements, key);

        // print match if found
        if (result >= 0) System.out.println(elements[result]);
    }
}

/**
 * An invocation handler that prints out the method name and parameters, then
 * invokes the original method
 */
class TraceHandler implements InvocationHandler
{
    private Object target;
    
    /**
     * Constructs a TraceHandler
     * @param t the implicit parameter of the method call
     */
    public TraceHandler(Object t)
    {
        target = t;
    }

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


        // print implicit argument
        System.out.print(target);
        // print method name
        System.out.print("^" + m.getName() + "(");
        // print explicit arguments
        if (args != null)
        {
            for (int i = 0; i < args.length; i++)
            {
                System.out.print(args[i]);
                if (i < args.length - 1) {
                    System.out.print(", ");
                }
            }
        }
        System.out.println(")");

        try {
            return m.invoke(target, args);
        } catch (InvocationTargetException e) {
            throw e.getCause();
        }
    }
}

class Employee32 implements Comparable<Employee32>
{
    private int age;

    @Override
    public int compareTo(Employee32 o) {
        return this.age - o.age;
    }

    public Employee32(int age) {
        this.age = age;
    }
}

相像是美好的,结果却很残酷,编译没有问题,运行时报错如下:

wwydr.chapter6.Employee32@5cad8086^compareTo(65)
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to wwydr.chapter6.Employee32
at wwydr.chapter6.Employee32.compareTo(ProxyTest.java:95)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at wwydr.chapter6.TraceHandler.invoke(ProxyTest.java:88)
at com.sun.proxy.$Proxy0.compareTo(Unknown Source)
at java.util.Arrays.binarySearch0(Arrays.java:2439)
at java.util.Arrays.binarySearch(Arrays.java:2379)
at wwydr.chapter6.ProxyTest.main(ProxyTest.java:41)


错误出现在这一句:return m.invoke(target, args);
args参数是Integer类型,target参数是Employee32类型,和我相像的两个都是Employee32类型不一致,我查了好多资料,居然都没有合适的解决办法,只能来此向各位请教,这究竟是什么原因,我该如何来解决这个问题.

  • 写回答

2条回答 默认 最新

  • CSDN专家-Time 2021-07-23 16:02
    关注

    用模板类型T

    评论

报告相同问题?

问题事件

  • 创建了问题 7月23日

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)