Макросы в Java?

Я знаю, что в Java нет макросов, но есть ли способ обхода:

#ifdef _FOO_FLAG_
import com.x.y.z.Foo;
#else
import com.a.b.c.Foo;
#endif

Оба класса Foo имеют одинаковые методы. Один из них - из сторонней библиотеки. Я хочу легко переключаться на библиотеку по умолчанию, меняя одну строку кода. Возможно ли это?

EDIT:
Оба класса находятся вне моего контроля (один из них - от проекта SQLCipher для Android, другой - от Android SDK). Мне нужно это, потому что на данный момент библиотека SQLCipher не работает на телефонах SAMSUNG.

Ответ 1

Нет, в Java нет часто используемого препроцессора (хотя вы могли бы использовать препроцессор C на вашем Java-коде, но я бы отговорил его, так как это было бы очень необычно и нарушало бы большинство инструментов, которые обрабатывают ваш код). Такие выборы обычно выполняются во время выполнения, а не во время компиляции в Java.

Обычный Java-путь для этого состоит в том, чтобы оба класса реализовали один и тот же интерфейс и ссылались на них только через интерфейс:

IFoo myFoo;
if (FOO_FLAG) { // possibly a public static final boolean
  myFoo = new com.x.y.z.Foo();
} else {
  myFoo = new com.a.b.c.Foo();
}

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

Ответ 2

То, как этот тип вещей обычно обрабатывается на Java, имеет инфраструктуру инъекции зависимостей, такую ​​как Spring или Guice. Например, в Spring у вас есть два разных "контекста приложений" для переключения между двумя реализациями, но остальная часть кода Java будет идентичной.

Единственный улов в том, что вашим com.a.b.c.Foo и com.x.y.z.Foo необходимо реализовать общий интерфейс - для них не достаточно просто использовать одни и те же методы, даже с хорошей инфраструктурой инъекций зависимостей.

Ответ 3

Вы также можете обнаружить наличие определенных классов во время выполнения, используя Class.forName(). Это позволяет развертывать одну и ту же сборку в разных средах/устройствах.

Ответ 4

Мой ответ, связанный с использованием C-препроцессора, был преобразован в комментарий того, кто, казалось, пропустил тот факт, что использование этого позволит вам написать:

#ifdef _FOO_FLAG_
import com.x.y.z.Foo;
#else
import com.a.b.c.Foo;
#endif

Ищите скрытый комментарий в вопросе.

В любом случае, поскольку все, что вам нужно, это управление версиями, здесь проще использовать препроцессор, который должен работать с настройкой android: http://prebop.sourceforge.net/

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