【问题标题】:Creating Non-Object Specific Methods创建非对象特定方法
【发布时间】:2018-07-06 01:14:32
【问题描述】:

是否可以制作一个使用对象作为参数的方法,但没有具体指定要传递的对象类型?该方法将尝试使用大多数对象具有的compareTo 方法。

另外,是否可以检查一个对象是否有compareTo 方法,如果没有则抛出异常?

【问题讨论】:

  • 使用带有约束的泛型。
  • 您正在寻找接口。
  • 您需要一个将Comparable<?> 作为参数的方法。
  • Comparable有一个接口,直接用就不用检查了
  • 但如果您需要将任何Object 传递给不一定implements Comparable 的方法,请使用instanceof 检查参数。如果它有compareTo() 但不是Comparable,则可以使用反射来检查。

标签: java object methods parameters


【解决方案1】:

您需要您的对象做的唯一一件事就是实现Comparable 接口。 Java 将确保您传入的任何内容在编译时都是类型安全的,这意味着您不必抛出任何类型的运行时异常。

从那里,您可以利用 Java 中的任何标准排序方法:

(请注意,对于Arrays.sort,它需要Object[],但如果违反Comparable 的约定,则会抛出异常。)

【讨论】:

    【解决方案2】:

    根据您的描述,在我看来,您要求的是使用强制转换:

    /**
     * @param  lhs
     * @param  rhs
     * @return the result of comparing lhs to rhs via compareTo
     * @throws NullPointerException
     *         if lhs or rhs is null
     * @throws ClassCastException
     *         if lhs or rhs does not implement Comparable or
     *         if lhs and rhs are not mutually comparable
     * @see    Comparable#compareTo(Object)
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    private static int compareByCasting(Object lhs, Object rhs) {
        Comparable compL = (Comparable) lhs;
        Comparable compR = (Comparable) rhs;
        return compL.compareTo(compR);
    }
    

    This is how methods like Arrays.sort work behind the scenes.

    也就是说,很少需要编写这样的代码,除非您正在编写非常低级的 API,例如 Arrays.sort。 Java 有静态类型,所以一般来说,目标是将类型检查推送到编译时进行编程,这样我们就不必运行程序来验证它是否正确。这就是我们使用接口和泛型等工具的原因。

    【讨论】:

      【解决方案3】:

      排序方法 [...] 对象数组

      如果所有这些对象都是同一类型并且实现可比较,则可以使用generics

      请注意,如果它们的类型不同,则需要编写自定义方法进行比较
      (即整数和字符串比较)

      private <A extends Comparable<A>> void bigger(A a, A b)
      {
          if(a.compareTo(b) > 0)
              System.out.println("a bigger");
          else
              System.out.println("b bigger");
      }
      

      请注意,这仅适用于相同类型的对象

      //works
      String a = "5";
      String b = "6";
      bigger(a, b);
      
      //compile error
      Integer c = 5;
      String d = "6";
      bigger(c, d);
      

      这适用于实现Comparable的东西

      在自定义对象上,通常很容易实现

      class Duck implements Comparable<Duck>
      {
          private int height;
          [...]
          public int compareTo(Duck other)
          {
              return height - other.height;
          }
      }
      

      这很酷,大多数sorting bits of the Java API 都是为处理Comparable 而构建的


      如果您不知道它们是 Comparables 并且坚持将所有内容都保留为对象,那么您很可能会卡在使用 Reflection

      int compare(Object a, Object b) throws NoSuchMethodException, IllegalAccessException, java.lang.reflect.InvocationTargetException
      {
          return (Integer)a.getClass().getMethod("compareTo", b.getClass()).invoke(a, b);
      }
      

      【讨论】:

      • 有没有办法只检查是否有一个名为compareTo的方法?我知道我可以只实现Comparable,但如果我可以只检查具体方法就好了。
      • @PeregrineLennert 它不会很漂亮,很可能需要Reflection。更推荐使用 Comparable 之类的接口
      • 好吧,我只是想知道,但我可以看到使用Comparable 比专门检查方法更容易。
      • 我对你使用反射表示严重的冒犯。这不是甚至是遥不可及的情况。如果您的对象不可比较,那么尝试对它们进行排序是没有意义的,因为它们的排序没有顺序。此外,您的代码只会抛出NoSuchMethodException除非他们实现Comparable。这是完全错误的。
      • 如果代码设法进入某种实现Comparable但不是真正Comparable的代码库,我可以使用这两个工具是git annotate 以及那个人的办公桌在哪里。不得不这样做完全破坏了泛型的意义。
      【解决方案4】:

      具有如下约束的通用自定义方法应该使您能够比较实现通用Comparable 接口的对象,因此,无需采用Object 类型的参数,然后确保它具有compareTo方法。

      public <T extends Comparable<T>> int comparer(T thiss, T that){
             // do logic
      }
      

      【讨论】:

      • 如果传递一个int和一个String怎么办?是否可以删除 U 并仅将 T 用于两者?
      • @phflack:这意味着他们可以与自己相提并论,所以是的。
      • @phflack 抱歉,我误读了这个问题。现在更新了答案。有任何问题请告诉我;)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-31
      • 1970-01-01
      • 2016-07-23
      • 2014-09-24
      • 2021-01-16
      相关资源
      最近更新 更多