سؤال

فيما يلي رسالة خطأ:

public static List<Comparable<?>> merge(Set<List<Comparable<?>>> lists) {
    List<Comparable<?>> result = new LinkedList<Comparable<?>>();
    HashBiMap<List<Comparable<?>>, Integer> location = HashBiMap.create();

    int totalSize;
    for (List<Comparable<?>> l : lists) {
        location.put(l, 0);
        totalSize += l.size();
    }

    boolean first;
    List<Comparable<?>> lowest; //the list with the lowest item to add
    int index;

    while (result.size() < totalSize) {
        first = true;

        for (List<Comparable<?>> l : lists) {
            if (! l.isEmpty()) {
                if (first) {
                    lowest = l;
                }
                else if (l.get(location.get(l)).compareTo(lowest.get(location.get(lowest))) <= 0) { //error here
                    lowest = l;
                }
            }
        }
        index = location.get(lowest);
        result.add(lowest.get(index));
        lowest.remove(index);
    }
    return result;
}

الخطأ هو:

The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>)

ماذا يحدث هنا؟ لقد صنعت نوع كل شيء Comparable حتى أتمكن من الاتصال .compareTo وفرز هذه القائمة. هل أستخدم الأدوية الجيرية بشكل غير صحيح؟

هل كانت مفيدة؟

المحلول

List<?> تعني "قائمة أي شيء" ، لذا فإن كائنين بهذا النوع ليسا متماثلان: يمكن للمرء أن يكون قائمة String, والآخر قائمة من BigDecimal. من الواضح أن هذه ليست هي نفسها.

List<T> يعني "قائمة أي شيء ولكن عندما ترى T مرة أخرى ، هو نفسه T".

يجب أن تخبر المترجم عندما تقصد نفس النوع في أماكن مختلفة. محاولة:

public static <T extends Comparable<? super T>> List<T> merge(Set<List<T>> lists) {
    List<T> result = new LinkedList<T>();
    HashBiMap<List<T>, Integer> location = HashBiMap.create();

تحرير] فماذا يفعل <T extends Comparable<? super T>> List<T> تعني؟ الجزء الأول يحدد النوع T مع الخصائص التالية: يجب أن تنفذ الواجهة Comparable<? super T> (أو Comparable<X> أين X يتم تعريفه أيضًا من حيث T).

? super T يعني أن النوع الذي Comparable الدعم يجب T أو واحدة من أنواعها الفائقة.

تخيل للحظة هذا الميراث: Double extends Integer extends Number. هذا غير صحيح في جافا ولكن تخيل ذلك Double هو مجرد Integer بالإضافة إلى جزء الكسر. في هذا السيناريو ، أ Comparable الذي يعمل ل Number يعمل أيضا ل Integer و Double لأن كلاهما يستمد من Number. لذا Comparable<Number> سوف ترضي super جزء ل T مستخدم Number, Integer أو Double.

طالما أن كل من هذه الأنواع تدعم Comparable واجهة ، وتلبية أيضا الجزء الأول من الإعلان. هذا يعني أنه يمكنك المرور Number ل T وسيعمل الرمز الناتج أيضًا عندما يكون هناك Integer و Double مثيلات في القوائم. اذا أنت Integer ل T, ، لا يزال بإمكانك الاستخدام Double لكن Number غير ممكن لأنه لا يرضي T extends Comparable بعد الآن (ال super جزء سيظل يعمل ، رغم ذلك).

الخطوة التالية هي فهم أن التعبير بين static و List يعلن فقط خصائص النوع T الذي يستخدم لاحقًا في الكود. بهذه الطريقة ، ليس عليك تكرار هذا الإعلان الطويل مرارًا وتكرارًا. إنه جزء من سلوك الطريقة (مثل public) وليس جزء من الكود الفعلي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top