簡體   English   中英

如何告訴編譯器兩個對象是相同的(但未知)類(帶有泛型)?

[英]How to tell compiler that two objects are of same - but unknown - class (with generics)?

請考慮以下代碼:

public class MyClass {

  public static void main(String[] args) {    
    Object o1 = getObject(Math.random());
    Object o2 = getObject(Math.random());
    if (o1.getClass().equals(o2.getClass()) { // two Cars or two Apples
      Comparable c1 = (Comparable) o1;
      Comparable c2 = (Comparable) o2;
      int x = c1.compareTo(c2); // unsafe
      System.out.println(x);
    )
  }

  public Object getObject(double d) { // given method that may not be changed
    if (d < 0.5) return (new Car()); // Car implements Comparable<Car>
    else return (new Apple()); // Apple implements Comparable<Apple>
  }

}

代碼可以工作(給定CatApple類),但是編譯器會警告操作不安全,因為我使用了不帶泛型的compareTo 但是,我不知道如何解決此問題,因為我不知道如何指定c1c2的類型相同-但未知-類型(在if子句中)。 有什么辦法(除了使用@SuppressWarnings以外)來解決此問題?

我知道這里有一個類似的問題: 如何告訴Java兩個通配符類型相同? 但是那里給出的答案似乎是針對問詢者的具體情況。 例如,它使用在我的上下文中不存在的鍵值映射。

由於條件if (o1.getClass().equals(o2.getClass()))保證兩個對象屬於同一類,因此可以忽略警告。 您可以抑制它。

但是,由於此時它們的類型是Object ,將它們ComparableComparable不安全的。 您可以通過一些較小的調整使其更安全,以使它們成為Comparable類:

public static void main(String[] args) {
    Comparable<?> o1 = getComparable(Math.random());
    Comparable<?> o2 = getComparable(Math.random());
    if (o1.getClass().equals(o2.getClass())) {
        // safe cast
        Comparable c1 = (Comparable) o1;
        Comparable c2 = (Comparable) o2;
        // safe comparison
        int x = c1.compareTo(c2);
        System.out.println(x);
    }
}

public Comparable<? extends Comparable<?>> getComparable(double d) {
    if (d < 0.5) return (new Car());
    return (new Apple());
}

這里的問題是,不能將Comparable<Car>Comparable<Apple>相互比較,因為Comparable<T>僅比較T s就具有“舒適”功能。 現在,我們為此付出了代價。

對於.equals並非如此。

我們正在嘗試什么

// WILL NOT WORK

if (o1.getClass().equals(o2.getClass()) { // two Cars or two Apples
  int x = comparison(o1.getClass(), o1, o2);
  System.out.println(x);
)

static <T extends Comparable<T>> int comparison(Class<T> type, T o1, T o2) {
    return type.cast(o1).compareTo(type.cast(o2));
}

這是Java的一個功能,它具有極少表現力的類型系統。

更新您的方法以處理可Comparable對象而不是Object對象。

public class MyClass {

  public static void main(String[] args) {    
    Comparable o1 = getObject(Math.random());
    Comparable o2 = getObject(Math.random());
    if (o1.getClass().equals(o2.getClass()) { // two Cars or two Apples
      int x = o1.compareTo(o2);
      System.out.println(x);
    )
  }

  public Comparable getObject(double d) { // given method that may not be changed
    if (d < 0.5) return (new Car()); // Car implements Comparable<Car>
    else return (new Apple()); // Apple implements Comparable<Apple>
  }

}

另一個替代實現:

public static void main(String[] args) {    
    Object o1 = getObject(Math.random());
    Object o2 = getObject(Math.random());
    if ( o1.getClass().equals(o2.getClass() ) && o1 instanceof Comparable ) {
      int x = getObject(o1).compareTo(o2);
      System.out.println(x);
    }

  }

  public static Object getObject(double d) { // given method that may not be changed
    if (d < 0.5) return ( new Car() ); // Car implements Comparable<Car>
    else return ( new Apple() ); // Apple implements Comparable<Apple>
  }

  public static <T> Comparable<T> getObject(Object o) {
      return (Comparable<T>)o;
  }

您可以使用instanceof運算符。 您可以將其編寫為:

if(c1 instanceof Integer && c2 instanceof Integer)
   int x = c.compareTo(c2);





or if(c1 instanceof String)
    String s = c1;

您可以通過這種方式工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM