предупреждение: [непроверено] непроверенный вызов compareTo(T) как члена сопоставимого типа raw

#java #linked-list #comparable #compareto #unchecked

Вопрос:

Я недавно возвращаюсь на Яву после 10 лет, и я довольно устал. Я пытаюсь запустить какой-то базовый код отсортированного списка, который у меня был. Этот код использовался для компиляции и запуска, но теперь я получаю следующее предупреждение:

 .LinkedList.java:30: warning: [unchecked] unchecked call to compareTo(T) as a member of the raw type Comparable
                    return _data.compareTo( ((Node)n)._data );
                                          ^
where T is a type-variable:
T extends Object declared in interface Comparable
 

Это код, выдающий предупреждение:

 static protected class Node implements Comparable
{
    public Node _next;
    public Comparable _data;
    
    protected Node(Comparable data, Node next)
    {
        _next = next;
        _data = data;
    }
    
    public int compareTo(Object n)
    {
        return _data.compareTo( ((Node)n)._data );
    }
    
    public String toString()
    {
        return _data.toString();
    }
    
} // end Node class
 

Насколько я понимаю, я больше не могу использовать compareTo() для необработанного типа, но я не уверен, как это исправить. Любая помощь приветствуется.
Также новичок в переполнении стека, так что простите меня, если я сделал это неправильно или пропустил, где на это уже был дан ответ.

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

1. Посмотрите документацию Comparable . Видите, как это определяется как Comparable<T> ? По этой причине вам нужно написать protected class Node implements Comparable<Node> .

2. Если действительно прошло 10 лет, вы, вероятно, были на Java 7, может быть, даже на Java 6. Было сделано много дополнительных улучшений, как в языке, так и в библиотеках. Было бы целесообразно изучить список изменений в каждой версии, чтобы понять, как избавиться от большого количества шаблонного кода, который раньше был необходим.

Ответ №1:

Существует два (три) различных типа заказа:

  1. Поведение естественного порядка, реализуемое самим классом
  2. Поведение порядка для конкретной задачи, реализованное в коде
  3. Смесь того и другого, потому что они совместимы.

Обычно:

Comparable является универсальным классом, поэтому вы должны фактически использовать Comparable<T> (T-тип класса), в вашем примере используйте его рефлексивно, Comparable<Node> чтобы компилятор знал, что у вас есть сопоставимый Node , который вы хотите сравнить с другим (сопоставимым) Узел.

Тип заказа 1: Comparable<T> используется, когда у вас есть естественный порядок элементов, и элементы сами определяют свое поведение при заказе.

Ваш код переделан:

1: Узлы, которые можно сравнить с Ts, что обычно проблематично:

 public class Node<T extends Comparable<T>> implements Comparable<T> {
    public Node<T>  _next;
    public T        _data;

    protected Node(final T data, final Node<T> next) {
        _next = next;
        _data = data;
    }

    @Override public String toString() {
        return _data.toString();
    }

    @Override public int compareTo(final T pO) {
        return _data.compareTo(pO);
    }

} // end Node class
 

2: Узел, который можно сравнить с другими узлами, и содержащийся в нем T также должен быть сопоставим:

Это реализация по умолчанию, которую вы бы использовали в своем случае.

 public class Node<T extends Comparable<T>> implements Comparable<Node<T>> {
    public Node<T>  _next;
    public T        _data;

    protected Node(final T data, final Node<T> next) {
        _next = next;
        _data = data;
    }

    @Override public String toString() {
        return _data.toString();
    }

    @Override public int compareTo(final Node<T> pO) {
        return _data.compareTo(pO._data);
    }

} // end Node class
 

Тип заказа 2: Использование заказа для конкретной задачи:

Это контрастирует с описанной выше ситуацией. Здесь не элемент определяет порядок, а стоящая перед вами задача:

Код для класса не обязательно должен (но все же может) указывать реализацию упорядочения. Но тогда заказ выполняется по определенному содержимому с определенным заказом Comparator :

 import java.util.ArrayList;
import java.util.Collections;

public class MyClass {

    public final int    mAge;
    public final String mName;
    public final float  mValue;

    protected MyClass(final int pAge, final String pName, final float pValue) {
        mAge = pAge;
        mName = pName;
        mValue = pValue;
    }

    @Override public String toString() {
        return "MyClass [mAge="   mAge   ", mName="   mName   ", mValue="   mValue   "]";
    }



    public static void main(final String[] args) {
        final ArrayList<MyClass> list = new ArrayList<>();
        list.add(new MyClass(12, "Chris", 13.7f));
        list.add(new MyClass(14, "Anna", 18.7f));
        list.add(new MyClass(33, "Bob", 3.7f));


        printList("Unordered", list);

        // sort by age
        Collections.sort(list, (p, q) -> p.mAge - q.mAge);
        printList("Sorted by age", list);

        // sort by Name
        Collections.sort(list, (p, q) -> p.mName.compareTo(q.mName));
        printList("Sorted by name", list);

        // sort by Value
        Collections.sort(list, (p, q) -> (int) Math.signum(p.mValue - q.mValue));
        printList("Sorted by value", list);
    }

    private static void printList(final String pMessage, final ArrayList<MyClass> pList) {
        System.out.println(pMessage);
        for (final MyClass item : pList) {
            System.out.println(item);
        }
        System.out.println();
    }

} 
 

… и, конечно, тип 3, где вы смешиваете и то, и другое, т. Е. implements Comparable<> где-то в смеси и используете это