Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javac等价于-D";?_Java_C++ - Fatal编程技术网

javac等价于-D";?

javac等价于-D";?,java,c++,Java,C++,有没有一种方法可以为java编译器提供运行java代码可以访问的某种变量? 在C/C++中,我可以给出compile-DKEY=VALUE,这将导致预处理器对KEY=VALUE有一个#define。然后,我可以在编译时检查此值,以影响正在编译的代码。 我找到了java的s-D,但这会将值放入java命令行的System.getProperty()。我希望参数在编译时给出,而不是调用时 -Akey[=value] 将信息传递给的命令行选项。在Java中没有类似的选项。编译时常量必须在源代码中声明

有没有一种方法可以为java编译器提供运行java代码可以访问的某种变量?
在C/C++中,我可以给出compile
-DKEY=VALUE
,这将导致预处理器对KEY=VALUE有一个
#define
。然后,我可以在编译时检查此值,以影响正在编译的代码。

我找到了
java
的s-D,但这会将值放入
java
命令行的
System.getProperty()
。我希望参数在编译时给出,而不是调用时

-Akey[=value]

将信息传递给的命令行选项。

在Java中没有类似的选项。编译时常量必须在源代码中声明,据我所知,没有预处理器

顺便说一句,您可以使用
java
命令行(-D args)的标志在运行时初始化java常量,这将模拟您正在寻找的内容

例:


javaxxx-Dfoo.bar=foobar调用,这样做会违反语言的设计。
-DKEY=VALUE
的作用是,在C/C++的预处理过程中,它实际上将源代码中的
替换为

Java没有预处理器,因此其机制不可用。如果你想要一些“等价物”,你必须质疑你的意思。如果不对源代码进行预处理,它就不会真正等效

另一方面,如果您希望它意味着将符号
的值设置为
,那么您将遇到一个问题,即无论如何都需要声明符号
,以确定其类型。在这种情况下,它只会是另一个带有约束的常量/变量


这意味着,即使有了这样一个特性,它实际上也不会改变生成的代码,而且您很难比定义att launch time的值更好。这就是为什么要通过
java
提供参数。

因为在java中没有预处理的概念,所以解决方案是设计自己的

人们可能会考虑使用标准的C预处理器或定制的预处理器来编译预处理的输出,但这样做的缺点是会复制文件,因此项目会变得更加复杂,开发环境的支持也会降低(比如跳转到语法错误的能力)

我的建议是通过注释使用注释,这些注释将引导自定义预处理器,并让它在编译之前进行替换

比如说,

   public static void main(String[] args) {
      int nDisks = 3;
      doTowers(nDisks, 'A', 'B', 'C');
   }
将成为

   public static void main(String[] args) {
      int nDisks = /*@NDISKS*/ 3 /**/;
      doTowers(nDisks, 'A', 'B', 'C');
   }
然后预处理器将有一个定义文件,如

NDISKS 5
提交代码

   public static void main(String[] args) {
      int nDisks = /*@NDISKS*/ 5 /**/;
      doTowers(nDisks, 'A', 'B', 'C');
   }
类似地,您可以使用

     doTowers(topN - 1, from, to, inter);
     /*!PRINT*/
     System.out.println("Disk "
     + topN + " from " + from + " to " + to);
     /**/
     doTowers(topN - 1, inter, from, to);
可以由预处理器将其转换为

您可以使用其他语法,但主要思想是

  • 注释代码保持可编译性
  • 预处理器替换是可逆的

使用java注释,可以动态生成附加代码,这些代码可以在命令行上配置。它允许生成更多的源代码、配置文件、xml文件等。。。主要限制是只允许(重新)生成新的源文件,不能修改现有的源文件

下面是一个关于如何允许从javac命令指定在Java代码中可见的参数的简短教程。这有多有用?例如,您可以指定一个布尔选项,该选项将禁用代码的某些部分,我确信可以使用proguard之类的工具删除这些部分的代码,甚至可以通过javac进行优化。其他用途是指定新版本号。这些用例主要是C++语言所使用的。 因此,您需要:

  • 允许处理器运行的虚拟注释类。在应用程序中只应指定一次
  • 一个处理器类,将为上面的伪注释运行,并生成选项类。它还将从javac命令行读取选项
  • 用于测试目的的虚拟主类
在编译主类之前,还必须编译处理器文件。当然,这只有在修改processor类时才能完成。这三个文件都在底部。现在编译如下(我在windows上):

编译处理器:

javac .\com\example\ConfigWritterAnnotationProcessor.java
javac -processor com.example.ConfigWritterAnnotationProcessor -AtextToPrint="Hello World!" -AenablePrint=true ./com/example/Main.java
然后使用附加参数Main.java访问处理器:

javac .\com\example\ConfigWritterAnnotationProcessor.java
javac -processor com.example.ConfigWritterAnnotationProcessor -AtextToPrint="Hello World!" -AenablePrint=true ./com/example/Main.java
就这样,现在您可以运行Main.class,它将使用编译期间生成的选项类,并设置上述参数。其内容如下:

package com.example;
public class Options {
    public static final String textToPrint = "Hello World!";
    public static final boolean enablePrint = true;
}

ProcessorStarteranotation.java

package com.example;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
public @interface ProcessorStarterAnnotation {
}
Main.java

package com.example;

@ProcessorStarterAnnotation
public class Main {
    public static void main(String[] args) {
      if ( com.example.Options.enablePrint ) {
        System.out.println(com.example.Options.textToPrint);
      }
      else {
        System.out.println("Print disabled");
      }
    }
}
ConfigWriterAnnotationProcessor.java

package com.example;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Map;
import java.util.Set;

@SupportedAnnotationTypes("com.example.ProcessorStarterAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedOptions({"textToPrint", "enablePrint"})
public class ConfigWritterAnnotationProcessor extends AbstractProcessor {
  private Map<String,String> options;

  @Override
  public synchronized void init(ProcessingEnvironment processingEnv) {
    super.init(processingEnv);
    options = processingEnv.getOptions();
  }

  @Override
  public boolean process(Set<? extends TypeElement> annotations,
                         RoundEnvironment currentRound) {

    if (!currentRound.processingOver()) {
      // This for-s are because processor is also run on newly created Options class.
      for (TypeElement te : annotations) {
        for (Element e : currentRound.getElementsAnnotatedWith(te)) {
          try {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Creating com.example.Options");
            JavaFileObject javaFile = processingEnv.getFiler().createSourceFile("com.example.Options");
            Writer w = javaFile.openWriter();
            try {
              PrintWriter pw = new PrintWriter(w);
              pw.println("package com.example;");
              pw.println("public class Options {");
              pw.println("    public static final String textToPrint = \"" + options.get("textToPrint") + "\";");
              pw.println("    public static final boolean enablePrint = " + options.get("enablePrint") + ";");
              pw.println("}");
              pw.flush();
            } finally {
              w.close();
            }
          } catch (IOException x) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                x.toString());
          }
        }
      }
    }
    return false;
  }
}
package.com.example;
导入javax.annotation.processing.*;
导入javax.lang.model.SourceVersion;
导入javax.lang.model.element.element;
导入javax.lang.model.element.TypeElement;
导入javax.tools.Diagnostic;
导入javax.tools.JavaFileObject;
导入java.io.IOException;
导入java.io.PrintWriter;
导入java.io.Writer;
导入java.util.Map;
导入java.util.Set;
@SupportedAnnotationTypes(“com.example.ProcessorStarterAnnotation”)
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@支持选项({“TextTopPrint”,“enablePrint”})
公共类ConfigWriterAnnotationProcessor扩展了AbstractProcessor{
私人地图选项;
@凌驾
公共同步void init(ProcessingEnvironment ProcessingEnvironment){
super.init(processingEnv);
options=processingEnv.getOptions();
}
@凌驾

公共布尔进程(SetJava没有C预处理器,也没有像
#define
@khelwood这样的东西。我是不是暗示它有?你不能,因为java没有预处理器。你可以使用像define这样的外部工具(比如or)。“正在运行的java代码”?正在编译的代码