Как предотвратить неявную компиляцию Java, когда класс существует в пути к классам?

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

public class Bob {
  public static void main(String[] args) {
    System.out.println(Tom.MESSAGE);
  }
}

public class Tom {
  public static String MESSAGE = "Hello World";
}

Если я попытаюсь скомпилировать Bob обычным способом, я также смогу неявно скомпилировать Tom.java, так как он распознается как зависимость от Bob.java. Это прекрасно работает.

Но теперь предположим, что я хочу поместить Тома в JAR-файл. Поэтому я собираю Tom.java и помещаю результаты в JAR-файл: libTom.jar. Теперь я компилирую с classpath, указывающим на libTom.jar. К сожалению, компилятор видит файл Tom.java и вызывает его компиляцию, а не использование класса в libTom.jar. Есть ли способ заставить компилятор пропустить неявную конструкцию Tom.java, если класс найден в пути к классам?

Я понимаю, что этот пример довольно надуманный. Будьте уверены, что существует более сложный и менее надуманный вариант использования, связанный с этой проблемой. Спасибо.


person Viper Bailey    schedule 01.06.2012    source источник
comment
Хотя я его не использовал, пробовали ли вы флаг -implicit для javac? в соответствии с выводом справки: -implicit:{none,class} Укажите, генерировать ли файлы классов для файлов, на которые неявно ссылаются, что звучит так, как вы хотите.   -  person Steve B.    schedule 02.06.2012
comment
почему это не ответ? @СтивБ.   -  person 11684    schedule 02.06.2012


Ответы (4)


Если в пути к классам есть два класса с одинаковыми именами и в одном пакете, трудно предсказать, какой из них будет выбран, когда java компилирует код. Если класс Tom существует в самом исходном коде, он обязательно будет подхвачен.

Один из способов избежать этого — поместить один из Tom в другой пакет. Другой способ — перенести текущий Tom в отдельный проект. Я понимаю, что любой из них может быть непрактичным для вас. Если это действительно необходимо, вы можете поэкспериментировать с написанием собственного ClassLoader. См. этот вопрос для справки: Jar hell: как использовать загрузчик классов для замены одной версии библиотеки jar на другую во время выполнения

person Hari Menon    schedule 01.06.2012

Похоже, что это просто невозможно, чего я и боялся с самого начала.

person Viper Bailey    schedule 02.06.2012

Да, вы можете сделать это, введя полное имя класса, т.е.

System.out.println(пакет.внешнего.Tom.MESSAGE);
System.out.println(текущий.пакет.Tom.MESSAGE);

person 11684    schedule 01.06.2012
comment
Извините, возможно, я был немного неясен в этом элементе. Рассматриваемые классы Tom являются одним и тем же классом. Таким образом, пакет будет таким же пакетом. Я просто хочу избежать неявной компиляции, когда компиляция не требуется из-за того, что класс уже скомпилирован. - person Viper Bailey; 02.06.2012
comment
ага ... Вы можете поместить исходный код в другой каталог и «импортировать» класс. - person 11684; 02.06.2012
comment
или вы можете взглянуть на JRebel. @ViperBailey - person 11684; 02.06.2012

Можете ли вы разделить файлы Java на отдельные исходные каталоги? Это имело бы смысл, поскольку вы могли бы создать свою банку из содержимого одного исходного каталога, а затем просто включить другой исходный каталог при компиляции всего остального набора файлов. Это хорошо работает в Eclipse. Еще лучше было бы использовать два проекта в Eclipse.

person davidfrancis    schedule 01.06.2012
comment
Из-за характера конкретной проблемы, которую я пытаюсь решить, это не сработает. - person Viper Bailey; 02.06.2012
comment
Возможно, вам придется объяснить больше о конкретной проблеме, а затем - person davidfrancis; 02.06.2012