Сбой статического импорта Java, когда импортируемый класс расширяет стороннюю библиотеку

Установка проблемы состоит из трех библиотек Java (я убрал все имена пакетов для удобства чтения, полные квалифицированные имена используются везде):

  1. external-lib: предоставляет абстрактный класс

    public abstract class AbstractExternal {}
    
  2. my-lib-A: предоставляет класс

    public class ClassA extends AbstractExternal {
        public static final String FOO = "foo";
    }
    

    external-lib находится в classpath my-lib-A.

  3. my-lib-B статически импортирует FOO из ClassA:

    import static ClassA.FOO;
    public class ClassB {
        private String foo = FOO;
    }
    

    my-lib-A находится в classpath my-lib-B, но external-lib не является.

Проблема: import static строка выдает следующую ошибку:

The type AbstractExternal cannot be resolved. It is indirectly referenced from required .class files,

Однако (1) при изменении ClassB на

import ClassA;
public class ClassB {
    private String foo = ClassA.FOO;
}

компилятор счастлив.

Однако (2) при добавлении второй абстракции два my-lib-A похожи

public class AbstractClassA extends AbstractExternal {}

а также

public class ClassA extends AbstractClassA {
    public static final String FOO = "foo";
}

статический импорт ClassA.FOO в приведенном выше примере работает.

Вопрос 1: почему import static ClassA.FOO терпит неудачу в то время как import ClassA с ClassA.FOO работает?

Вопрос 2: почему import static ClassA.FOO работает, когда он расширяет другой класс из my-lib-A, который затем расширяет AbstractExternal?

Редактировать: важная информация: речь идет о компиляторе Eclipse для Java (ECJ).

Редактирование 2: javac синхронизирован с ECJ и может компилировать обычный импорт и доступ к классам в ClassB, в то время как статический импорт не выполняется.

1 ответ

Ecj в идеале "не должен" сообщать об этой ошибке. Я подал ошибку 533890, чтобы отследить это.

Общая тема всех ошибок этого сообщения ("... не может быть решена. На нее косвенно ссылаются...") - это конфликт между:

  1. желая полного семантического анализа, который знает обо всех соответствующих классах и
  2. желая устойчивости, если путь сборки не содержит все классы, от которых зависит текущий класс (косвенно).

Очевидно, что JLS не определяет, как компиляторы должны обрабатывать неполные пути сборки, но для удобства пользователей не следует сообщать об ошибках, если семантический анализ может избежать изучения определенных косвенных зависимостей.

Где и когда этого действительно можно избежать, необходимо проверять (и реализовывать) на индивидуальной основе, но данный пример, вероятно, квалифицируется как случай, которого можно избежать.

Пока эта проблема не будет решена, проблему можно избежать, если external-lib виден также my-lib-B (например, используя зависимость проекта). В таких модульных системах, как OSGi или JPMS, было бы неплохо my-lib-A "реэкспорт" своей зависимости external-lib, поскольку его класс API ClassA является "неполным" для клиентов, которые не могут видеть AbstractExternal,

Другие вопросы по тегам