我可以在Java源文件中使用宏吗?

时间:2011-06-29 17:52:34

标签: java macros

在我的程序中,我多次使用控制台读取整数。每次,我都需要输入这一行。

new Scanner(System.in).nextInt(); 

我习惯于C / C ++,我想知道我是否可以定义类似

的内容
#define READINT Scanner(System.in).nextInt(); 

然后,在我的java程序的每个地方,我都可以将表格控制台视为

int a = new READINT;

但是我读过表格书Java不支持宏。

有人请解释我为什么会这样,我可以用其他方式做到这一点。

8 个答案:

答案 0 :(得分:142)

可以,但你不应该

不应该部分:

不应该因为以这种方式使用预处理器is considered bad practice,并且有越来越多的Java惯用方法来解决这个用例。


可以部分:(*)

Java本身不支持宏。另一方面,您可以通过C pre processor(简称CPP)管理源代码,就像C / C ++编译链一样。

这是一个演示:

<强> src/Test.java

#define READINT (new java.util.Scanner(System.in).nextInt())

class Test {
    public static void main(String[] args) {
        int i = READINT;
    }
}

cpp命令:

$ cpp -P src/Test.java preprocessed/Test.java

<强>结果:

class Test {
    public static void main(String[] args) {
        int i = (new java.util.Scanner(System.in).nextInt());
    }
}

<强>编译:

$ javac preprocessed/Test.java


更好的解决方法:

您可以使用静态方法编写自己的实用程序类:

import java.util.Scanner;
class StdinUtil {
    public final static Scanner STDIN = new Scanner(System.in);
    public static int readInt() {
        return STDIN.nextInt();
    }
}

当您想要使用它时,您可以静态导入readInt方法:

import static StdinUtil.readInt; 

class Test {
    public static void main(String[] args) {
        int i = readInt();
    }
}

(或static import StdinUtil.STDIN;并使用STDIN.nextInt()。)


最后,一则轶事

我自己在Java代码上使用了CPP预处理方法一次!我正在为课程创建编程作业。我希望能够从参考解决方案中轻松提取代码框架。所以我只使用了一些#ifdef来过滤出解决方案的“秘密”部分。这样我就可以维护参考解决方案,并轻松地重新生成代码框架。


此帖子已被重写为文章here


(*)因为我讨厌用“你不应该”回答问题。此外,一些未来的读者可能有充分的理由希望将cpp与Java源一起使用!

答案 1 :(得分:12)

否。 Java(该语言)不支持任何类型的宏。

但是,某些构造可以伪造或包裹。虽然这个例子很愚蠢(你为什么每次都要创建一个新的扫描仪!?!?!),但下面显示了它是如何实现的:

int nextInt() {
   return new Scanner(System.in).nextInt(); 
}
...
int a = nextInt();
int b = nextInt();

更多更好:

Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int b = scanner.nextInt();

快乐的编码。


评论:

静态方法可以在不需要对象调用它们的情况下调用。但是,在大多数情况下,一个已经在对象中。考虑:

public class Foo {
   static int nextIntStatic() {
     return 13;
   }

   int nextInt() {
     return 42;
   }

   void realMain () {
     // okay to call, same as this.nextInt()
     // and we are "in" the object
     int ni = nextInt();
   }

   public static void main(String[] args) {
      // okay to call, is a static method
      int nis = nextIntStatic();
      Foo f = new Foo();
      f.realMain();
   }
}

答案 2 :(得分:2)

Java不支持宏只是因为Java的设计者选择不包含该功能。更长的答案是Java没有像C / C ++那样的预处理器,也无法执行预处理器通常会执行的功能。我实现它的方法就是创建一个封装Scanner构造函数调用的包装类。也许像是

public static int readInt(){
  return new Scanner(System.in).nextInt();
}

或者,更好的是,

public class ScannerWrapper{
  private static Scanner instance = null;

  public static int readInt(){
   if (instance == null){
     instance = new Scanner(System.in);
   }

   return instance.nextInt();
 }

答案 3 :(得分:0)

Java不支持宏。 IIRC,语言设计者认为宏和由此产生的预分析器是不必要的和不合需要的并发症。

改为使用函数:

public int readInt(Scanner inp) {
    return inp.nextint();
    }

其他地方:

Scanner input=new Scanner(System.in);

...


int a=readInt(input);

另请注意,我创建了一次扫描程序并重复使用它。

答案 4 :(得分:0)

Java中没有宏观概念。如果你这么做,那么每次实例化一个新的Scanner是个坏主意。定义一个公共静态Scanner,然后每次重用它:

public class YourClass {
  public static final Scanner SCANNER= new Scanner(System.in);
  ...
}

// Somewhere in your code
YourClass.SCANNER.nextInt();

答案 5 :(得分:0)

如果你想使用C风格的宏,那么有人写了一个预处理器http://www.slashdev.ca/javapp/我不知道它有多好。

答案 6 :(得分:0)

例如,您可以使用Java Primitive Specializations Generator

/* define READINT //
new Scanner(System.in).nextInt();
// enddefine */

...

int a = /* READINT */0/**/;

答案 7 :(得分:-1)

使用实用程序类和静态导入。

实用程序类:

package my.utils;

public class ScannerUtils {
  private ScannerUtils() {}

  public static int readInt() {
    return new Scanner(System.in).nextInt();
  }
}

使用实用程序类:

package my.examples;

import static my.utils.ScannerUtils.*;

class Example {
  void foo() {
    int i = readInt();
  }
}

正如其他人所说,您应该缓存扫描仪,但这是一个单独的主题。