java Java中的宏?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7914804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 21:59:55  来源:igfitidea点击:

Macros in Java?

java

提问by Caner

I know there are no macros in Java, but is there a workaround to do something like this:

我知道 Java 中没有宏,但是是否有解决方法可以执行以下操作:

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

Both Fooclasses have the same methods. One of them is from a 3rd party library. I want to be able to switch to default library easily by changing a single line of code. Is this possible?

两个Foo类都有相同的方法。其中之一来自第 3 方库。我希望能够通过更改一行代码轻松切换到默认库。这可能吗?

EDIT:
Both classes are out of my control(one of them is from SQLCipher for Android project, other one is from Android SDK). I need this because SQLCipher library doesn't work on SAMSUNG phones at the moment.

编辑:
这两个类都不受我的控制(其中一个来自 SQLCipher for Android 项目,另一个来自 Android SDK)。我需要这个,因为 SQLCipher 库目前不适用于 SAMSUNG 手机。

回答by Joachim Sauer

No, there is no commonly used pre-processor in Java (although you coulduse the C preprocessor on your Java code, but I'd discourage it, as it would be very unusual and would break most tools that handle your code). Such selections are usuallydone at runtime rather than compile-time in Java.

不,Java 中没有常用的预处理器(虽然您可以在 Java 代码上使用 C 预处理器,但我不鼓励它,因为它非常不寻常,并且会破坏大多数处理您代码的工具)。这种选择通常在运行时完成,而不是在 Java 编译时完成。

The usual Java-way for this is to have both classes implement the same interface and refer to them via the interface only:

通常的 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();
}

If this is not possible (for example if at least one of the Fooclasses is not under your control), then you can achieve the same effect by an abstract FooWrapperclass (or interface) with two different implementations (XYZFooWrapper, ABCFooWrapper).

如果这是不可能的(例如,如果至少有一个Foo类不在您的控制之下),那么您可以通过FooWrapper具有两个不同实现 ( XYZFooWrapper, ABCFooWrapper)的抽象类(或接口)来实现相同的效果。

回答by mergeconflict

The way this sort of thing is typically handled in Java is with a dependency injectionframework such as Spring or Guice. In Spring, for example, you'd have two different "application contexts" to switch between the two implementations, but the rest of the Java code would be identical.

在 Java 中处理这类事情的方式通常是使用依赖注入框架,例如 Spring 或 Guice。例如,在 Spring 中,您将有两个不同的“应用程序上下文”来在两个实现之间切换,但其余的 Java 代码将是相同的。

The only catch is that your com.a.b.c.Fooand com.x.y.z.Foodo need to implement a common interface -- it's not good enough for them to simply have the same methods, even with a nice dependency injection framework.

唯一的问题是你com.a.b.c.Foocom.x.y.z.Foo你确实需要实现一个公共接口——即使有一个很好的依赖注入框架,他们仅仅拥有相同的方法是不够的。

回答by JimmyB

You can also detect the presence of certain classes at runtime using Class.forName(). This allows you to deploy the same build to different environments/devices.

您还可以使用Class.forName()在运行时检测某些类的存在。这允许您将相同的构建部署到不同的环境/设备。

回答by Josh S

My answer linking to how to use the C-preprocessor was converted to a comment by someone who seemed to miss the fact that using that would preciselyallow you write:

我链接到如何使用 C 预处理器的答案被转换为评论的人似乎错过了使用它可以准确地允许您编写的事实:

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

Look for the hidden comment under the question.

查找问题下方的隐藏评论。

Anyway since all you need is versioning, here's a simpler to use preprocessor that should work with the android setup: http://prebop.sourceforge.net/

无论如何,由于您只需要版本控制,这里有一个更简单的预处理器,它应该适用于 android 设置:http: //prebop.sourceforge.net/

If what you really want is two builds, then wrapping classes or writing code to choose at run time is a waste of effort and unnecessary complexity.

如果您真正想要的是两次构建,那么在运行时包装类或编写代码进行选择是浪费精力和不必要的复杂性。