Проблема с неограниченным интерфейсом Java Generic - PullRequest
3 голосов
/ 19 августа 2011

Рассмотрим следующий простой код

import java.util.*;

public class MainTest<T extends Object1<?,?>> {
    List<T> list;

    public MainTest(List<T> l) {
        this.list=l;
    }
    public int testCompare() {
        // fails to compile here
        return list.get(0).compareTo(list.get(1));
    }

    public static void main(String[]args) {
        List<Object1Impl> list = new ArrayList<Object1Impl>();
        list.add(new Object1Impl());
        list.add(new Object1Impl());

        MainTest<Object1Impl> test = new MainTest<Object1Impl>(list);
        System.out.println(test.testCompare());
    }
}

interface Object1<E, V> extends Comparable<Object1<E,V>> { }
class Object1Impl implements Object1<Integer, Integer>{
    public int compareTo(Object1<Integer, Integer> o) { return 0; }
}

Я знаю, что в этом случае программа не будет компилироваться (происходит сбой при testCompare (), поскольку T расширяется неограниченно Object1<?,?>).Есть ли альтернатива, чтобы это исправить, кроме MainTest<T extends Object1<E,V>,E,V>?

РЕДАКТИРОВАТЬ: сообщение об ошибке:

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

Я прочитал книгу по эффективной Java, но все еще не могу придумать решение..

Кроме того, почему, если я изменю интерфейс Object1 на абстрактный класс, программа без проблем скомпилируется?Это действительно озадачивает меня ...

РЕДАКТИРОВАТЬ: когда я имею в виду переход на абстрактный класс выглядит следующим образом

abstract class Object1<E, V> implements Comparable<Object1<E,V>>{ 
    public int compareTo(Object1<E,V> o) { return 0; }
}

class Object1Impl extends Object1<Integer, Integer>{ }

это будет работать (только если вы используете Eclipse, компиляция его вручную с использованием javac неработа) но я понятия не имею, почему

1 Ответ

4 голосов
/ 19 августа 2011

Это правильно;компилятор не может проверить, что list.get(0) и list.get(1) относятся к одному и тому же типу;один может быть Object1<String, Integer>, а другой Object1<BigDecimal, Double>.

Чтобы убедиться, что они одного типа, вам необходимо связать эти типы:

public class MainTest<A,B,T extends Object1<A,B>> {
    List<T> list;

    public MainTest(List<T> l) {
        this.list=l;
    }
    public int testCompare() {
        // fails to compile here
        return list.get(0).compareTo(list.get(1));
    }

    public static void main(String[]args) {
        List<Object1Impl> list = new ArrayList<Object1Impl>();
        list.add(new Object1Impl());
        list.add(new Object1Impl());

        MainTest<Integer, Integer, Object1Impl> test = new MainTest<Integer, Integer, Object1Impl>(list);
        System.out.println(test.testCompare());
    }
}

Насколько я знаю, Java не позволяет связывать типы параметров с классамибез указания их.

...