12

在 Java 中是否可以像在 C/C++ 中那样做某种 #ifdef 事情?

例子:

class Test
{
    public static final boolean ANDROID = false;

    public Test()
    {
        if (ANDROID)
        {
            // do stuff that won't compile if not on android
        }
        else
        {
            // do stuff that should be only done on desktop
        }
    }
}

请注意,即使ANDROIDis false,如示例中所示,它仍会尝试编译 内部的代码if,即使它不会(也不应该)编译。

我正在寻找一种进行条件编译的方法——编译器甚至不应该查看ifif ANDROIDis false

我的问题的上下文是我在 Eclipse 中有一个处理应用程序。我在两个单独的项目中同时使用正常的 Processing 和 Processing for Android,但我希望能够在彼此之间移动项目的源代码而不会出现编译器错误。例如,我希望能够拥有可以从 Android 项目移动到桌面项目的源代码文件,并且只需要更改一些东西——例如,更改ANDROID = trueANDROID = false.

我真的需要它是条件编译,因为当我将源代码从Android项目复制到桌面项目时,桌面库显然不会包含Android库,然后源代码甚至不会编译。

编辑:所以现在我知道 Java 中没有预处理器,我的问题是:有没有其他方法可以在我的项目中使用此功能(只需非常小的更改即可将源代码从一个复制到另一个)必须手动 [un] 注释特定的代码片段并且必须记住它们在哪里?

编辑 2:这不是另一个问题的重复,因为我的问题包含可能包含编译器错误的代码,而作为副本关闭的问题没有。(另一个问题只涉及即使没有#ifdefs 也能正常编译的代码。)为了解释,另一个问题的最高评价(和接受)的答案是关于已编译但根本不在字节码中发出的代码。但是,我的问题涉及最初甚至无法编译的代码。

4

5 回答 5

3

由于 Java 本身不包含预处理器,因此您有责任在编译之前手动执行预处理器。c预处理器是m4,你可以自己运行。

于 2013-10-30T13:55:14.360 回答
3

正如其他人所说,您的实际问题的答案是否定的。

但是,您可以通过隔离 Android 或桌面代码来解决您的问题。您可以通过在 eclipse 中拥有三个独立的项目来做到这一点:

  • 核心:这是两个版本之间存在的“共享”代码。
  • Android:这仅包含在 Android 上运行的代码。
  • 桌面:这仅包含在桌面上运行的代码。

您的 Android 和桌面项目都将在其类路径中包含 Core 项目。在 Eclipse 中,您可以通过转到 Java 构建路径,然后单击“项目”选项卡,然后将核心项目添加到“必需项目”列表中来完成此操作。

然后您将设置您的代码,以便您的 Android 和桌面项目是您实际部署的项目,并且您的核心项目包含它们之间共享的代码。这是一个简单的例子。假设我们有一个如下所示的示例类:

public class Adder{
   public void addAndPrint(int x, int y){

      //code that will work on both Android and desktop
      int sum = x+y;

      if (ANDROID){
         //code that will only work on Android
         Log.v("example", "Sum:" + sum);
      }
      else{
         //code that will only work on desktop
         System.out.println("Sum: " + sum)
      }
   }
}

您可以通过重构代码以隔离可在桌面和 Android 上运行的“核心”代码来解决此问题。像这样的东西:

//example core class
public class CoreAdder{

   Printer printer;

   public CoreAdder(Printer printer){
      this.printer = printer;
   }

   public void addAndPrint(int x, int y){
      int sum = x+y;
      printer.print("Sum: " + sum);
   }
}

//example core interface. We might print differently on
//Android and Desktop, so implement this interface in each.
public interface Printer{
   public void print(String printMe);
}

然后,您将隔离仅适用于桌面的代码:

//on desktop, use System.out.println()
public class DesktopPrinter implements Printer{
   public void print(String printMe){
      System.out.println(printMe);
   }
}

//on desktop, entry point is main()
public class DesktopMain{
   public static void main(String... args){
      DesktopPrinter printer = new DesktopPrinter();
      CoreAdder adder = new CoreAdder(printer);
      adder.addAndPrint(1, 2);
   }
}

以及仅适用于 Android 的代码:

//on Android, use a logger
public class AndroidPrinter implements Printer{
   public void print(String printMe){
      Log.v("example", "index=" + i);
   }
}

//on Android, entry point is Activity
public class AndroidActivity extends Activity{

   public void onCreate(Bundle savedInstanceState) {
      AndroidPrinter printer = new AndroidPrinter ();
      CoreAdder adder = new CoreAdder(printer);
      adder.addAndPrint(1, 2);
   }
}

请注意,这只是一个示例,我知道两者都System.out.println()可以Log.v()在任何一个平台上工作。但想法是一样的:将您的项目拆分为多个项目,并使用接口抽象出平台之间变化的行为。

于 2015-07-30T11:55:58.257 回答
1

Java 中没有 C、C++ 等预处理器。您所能做的就是注释掉代码。

于 2013-10-30T13:52:53.400 回答
0

不,Java 中没有可以将代码块隐藏到 JVM 的预处理器之类的东西。

编辑:虽然您当然可以针对您的代码库运行任何程序来对其进行预处理,但请考虑您是否真的想要这个。Android 代码将在时间上与其他 Java 代码有更多的差异,并且您的代码将被那些类似 #ifdef 的语句所淹没。您的 IDE 仍会看到它们并在两个代码区域中为您提供错误。在这种情况下,只用它创建两个项目要容易得多,或者这是我的建议,创建一个独立于平台的库,您将其包含在两个项目中并包含您需要的功能。

于 2013-10-30T13:52:56.020 回答
0

像在 C 中一样使用#ifdef和朋友,并在编译之前通过 C 预处理器运行 Java 源代码。

对于 gcc,预处理器称为 cpp,对于 VC,它是使用选项的 cl.exe /P

于 2013-10-30T18:30:22.803 回答