Метод, который существует ... нет? - PullRequest
3 голосов
/ 04 ноября 2011

Код (который компилируется):

    for (Method m : ImmutableList.class.getMethods()) {
        System.out.println(m);
    }

    ImmutableList.copyOf(Arrays.asList(new PlayerLevel[0]));

Вывод (аннотированный и сокращенный):

public final void com.google.common.collect.ImmutableList.add(int,java.lang.Object)
----> public static com.google.common.collect.ImmutableList com.google.common.collect.ImmutableList.copyOf(java.lang.Iterable)
public static com.google.common.collect.ImmutableList com.google.common.collect.ImmutableList.copyOf(java.util.Iterator)
                 (lots of other methods)

java.lang.NoSuchMethodError: com.google.common.collect.ImmutableList.copyOf(Ljava/util/Collection;)Lcom/google/common/collect/ImmutableList;

А?

(Если журналы недостаточно четкие, я получаю сообщение об ошибке, говорящее, что ImmutableList.copyOf(List) - это не метод, а циклический просмотр всех методов, которые я вижу, - copyOf(Iterable) и List implements Iterable.)

1 Ответ

6 голосов
/ 04 ноября 2011

Оба метода совместимы во время компиляции . Но время выполнения - это еще один зверь. Я предполагаю, что ваш код компилируется с более старой версией Коллекций Google, но работает с более новой версией.

Редактировать : Что происходит в деталях:

Учитывая строки

List<String tmpArray = Arrays.asList(new PlayerLevel[0]);
ImmutableList.copyOf(tmpArray);

компилятор начинает искать подходящий метод в ImmutableList с именем copyOf и одним параметром , совместимым со статическим типом List<String>. Версия класса, видимая для компилятора, предлагает ровно одно совпадение:

ImmutableList.copyOf(Collection<T> arg0);

Обратите внимание, что компилятор не заинтересован в фактическом типе tmpArray, только в статическом типе (он же «формальный тип»). ) считается.

Компилятор записывает подпись выбранного метода в файл класса.

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

ImmutableList.copyOf(Collection<T> arg0);

и выполняет поиск (не поиск !) На ImmutableList для точно заданной подписи. Совместимость здесь не имеет значения, это была работа компилятора. Вы получите те же результаты, если будете использовать отражение следующим образом:

ImmutableList.class.method("copyOf", Collection.class);

В обоих случаях Java просто выполняет поиск, используя точно заданного типа. Он не выполняет поиск типа «метод (ы) возврата, который может быть вызван с данным типом».

В вашем случае класс времени выполнения и класс времени компиляции различаются. Поэтому загрузчик классов / компоновщик не может выполнить поиск.

Шаг назад

Эта проблема показывает различные уровни совместимости:

  • Двоичная совместимость : добавьте новую банку и все.
  • Совместимость с исходным кодом : Вы должны скомпилировать исходный код, но вам не нужно его менять.
  • Поведенческая совместимость или Семантическая совместимость : код клиента должен быть изменен.

Эти ключевые слова можно использовать для просмотра этого сайта или в Google для получения дополнительной информации. Хорошим справочником по двоичной совместимости являются три части Развивающихся API на основе Java .

...