java generics — Метод сравнения (захват №1-оф ?) в сопоставимом типе не применим для аргументов

#java #generics

#java #generics

Вопрос:

Итак, я хочу сделать это:

 public interface IFieldObject {
    public Comparable get();
}

public interface IFieldCondition {
    public boolean apply(IFieldObject field, Comparable compare);
}

public class EqualTo implements IFieldCondition {
    public boolean apply(IFieldObject field, Comparable compare) {
        return (field.get().compareTo(compare) == 0);       
    }    
}
  

но Eclipse выдает мне предупреждения:

Безопасность типа: Метод compareTo(Object) принадлежит к сопоставимому необработанному типу. Ссылки на сопоставимый универсальный тип должны быть параметризованы

Итак, я превратил это в:

 public interface IFieldObject {
    public Comparable<?> get();
}

public interface IFieldCondition {
    public boolean apply(IFieldObject field, Comparable<?> compare);
}

public class EqualTo implements IFieldCondition {
    public boolean apply(IFieldObject field, Comparable<?> compare) {
        return (field.get().compareTo(compare) == 0);       
    }
}
  

который не компилируется из-за:

Метод compareTo(захват #1-оф ?) в сопоставимом типе не применим для аргументов (Comparable)

Каков правильный способ сделать это? (без предупреждений, следующих за идиоматическим Java >= 1.6)

Ответ №1:

В настоящее время у вас нет гарантии, что тип, возвращаемый field.get() , действительно сопоставим с типом, указанным методом. В идеале, сделать все это универсальным, например:

 public interface IFieldObject<T extends Comparable<T>> {
    public T get();
}

public interface IFieldCondition<T> {
    public boolean apply(IFieldObject<T> field, Comparable<T> compare);
}

public class EqualTo<T> implements IFieldCondition<T> {
    public boolean apply(IFieldObject<T> field, Comparable<T> compare) {
        return (field.get().compareTo(compare) == 0);       
    }
}
  

Вы, без сомнения, могли бы сделать это более общим, используя дополнительные захваты, но это отправная точка.

Комментарии:

1. Я хотел бы избежать дополнительных спецификаций для IFieldObject<T …> . Похоже, что версия Java «старой школы» просто «работает», и она более компактна, но я понимаю суть. Я действительно предпочел бы ошибку во время выполнения, чем всю эту типизацию 🙂

2. Один из способов, который я нахожу удобным для чтения универсальных методов, заключается в следующем: для всех типов T get() возвращает сопоставимый<T> .

3. чтобы сделать его еще лучше, <T extends Comparable<? super T>> , заставить его работать для подклассов сопоставимых типов

Ответ №2:

Как насчет этого?

 public interface IFieldObject {
    public<T> Comparable<T> get();
}

public interface IFieldCondition {
    public boolean apply(IFieldObject field, Comparable<?> compare);
}

public class EqualTo implements IFieldCondition {
    public boolean apply(IFieldObject field, Comparable<?> compare) {
        return (field.get().compareTo(compare) == 0);       
    }
}
  

Комментарии:

1. выглядит хорошо! можете ли вы указать мне на ресурс, который объясняет разницу между «общедоступным сопоставимым<?> foo()» и «общедоступным <T> Сопоставимым<T> foo()»?

2. Проверьте Java generic methods