【问题标题】:How to overide equals for array in Java?如何在Java中覆盖数组的equals?
【发布时间】:2012-08-30 19:50:24
【问题描述】:

我希望覆盖 int[] 数组的等号。使得以下将是正确的

int[] a = {1,2,3};
int[] b = {1,2,3};
System.out.println(a.equals(b));

有没有办法做到这一点?

【问题讨论】:

  • 使用Arrays.equals()不是最简单的方法吗?
  • Java 没有任何方式覆盖运算符。它在某些地方是一个非常有争议的主题,而在其他地方则是非黑即白的,这就是为什么他们选择将它排除在 Java 语言之外的原因。老实说,我希望允许重写以使 Java 不那么冗长,但可惜,事实并非如此。 This question 详细介绍。
  • HashSet 使用 equals(),所以我不能只制作 HashSet 并检查其中是否有数组。
  • 另外,int[] a = b 不会使它们相等,因为它们会指向内存中的相同位置吗?

标签: java


【解决方案1】:

覆盖int[]equals 方法既不可能也没有必要。你想要的功能可以通过Arrays.equals(int[], int[])来实现。

int[] a = {1,2,3};
int[] b = {1,2,3};
System.out.println(Arrays.equals(a, b));

【讨论】:

    【解决方案2】:

    数组是 Java 的低级结构,所以你不能创建子类,所以你不能覆盖方法。但是您可以使用 java.util.List 而不是数组。现代 JRE 在数组和列表方面表现出相同的性能。

    【讨论】:

    • +1 用于使用列表 - 特别是,ArrayList 几乎总是比使用数组更可取(除非您正在编写特别低级的代码)
    【解决方案3】:

    您不能直接覆盖数组上的 equals - 数组是 Java 中的原始构造,您不能覆盖作用于它们的方法或运算符。

    您应该考虑使用ArrayLists 而不是数组 - ArrayLists 提供了一个 equals() 实现,可以按照您的要求工作(以及数组没有的许多其他有用功能,例如添加列表中的新元素等)

    【讨论】:

      【解决方案4】:

      这里的其他答案是正确的,因为您实际上应该只使用Arrays.equals() 或切换到使用List<Integer> 而不是int[]

      但是,您想要做的事情几乎可以使用反射和javassist.util.proxy.ProxyFactory。以下是一些或多或少可以解决问题的示例代码:

      public static void main(String[] args) throws Exception {
          int[] test = {0, 1, 2, 3};
          int[] empty1 = {};
          int[] empty2 = {};
      
          Class clss = int[].class;
          ProxyFactory factory = new ProxyFactory();
          factory.setSuperclass(clss);
          factory.setFilter(new MethodFilter() {
               public boolean isHandled(Method m) {
                   // ignore finalize()
                   return !m.getName().equals("finalize");
               }
           });
          factory.setHandler(new IntArrayEqualsHandler());
      
          Class newArrayClass = factory.createClass();
      
          int[] specialArray = (int[])newArrayClass.newInstance();
          System.out.println(empty1.equals(empty2));
          System.out.println(specialArray.equals(empty1));
          System.out.println(specialArray.equals(empty2));
          System.out.println(specialArray.equals(test));
      }
      
      private static class IntArrayEqualsHandler implements MethodHandler {
          @Override
          public Object invoke(Object thisObj, Method method, Method original, Object[] params) throws Throwable {
              if (method.getName().equals("equals")) {
                  int[] left = (int[])thisObj;
                  int[] right = (int[])params[0];
                  return Arrays.equals(left, right);
              }
              return original.invoke(thisObj, params);
          }
      
      }
      

      不幸的是,这不起作用,因为int[].class 在语言中被声明为final,所以即使使用反射也不能扩展它。至少据我所知。您可以使用 remove the 'final' modifier from a field 的一些技巧,但似乎没有等效的技巧可用于从整个类中删除 final 修饰符。

      如果有这样的事情,您可以使用上面的代码或类似的代码在运行时生成 int[] 的自定义子类,以实现您所需的 equals() 行为。

      真的,虽然这比它的价值更麻烦,尤其是当您开始研究如何在项目的其余部分中实际使用自定义子类时。因此,考虑到您的所有情况, 最好使用Arrays.equals()List<Integer>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-24
        • 1970-01-01
        • 2012-04-10
        • 2020-06-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多