Java 源文件中可以有宏吗

发布于 2024-11-18 03:27:27 字数 363 浏览 1 评论 0原文

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

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

我习惯了 C/C++,我想知道是否可以定义类似的东西

#define READINT Scanner(System.in).nextInt(); 

,然后,在我的 java 程序中的每个地方,我都可以读取表单控制台,

int a = new READINT;

但我读表单书籍 Java 不支持宏。

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

In my program I'm reading integers form console many times. Every time, I need to type this line.

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

I'm used to C/C++ and I'm wondering if I can define something like

#define READINT Scanner(System.in).nextInt(); 

and then, in every place in my java program I can read form console as

int a = new READINT;

But I read form books Java does not support macros.

Someone please explain me why is it so, and can I do this in any other way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

夜未央樱花落 2024-11-25 03:27:27

可以,但您不应该

##不应该部分:

不应该因为以这种方式使用预处理器首先被认为是不好的做法,并且有更好、更惯用的 Java 方法来解决这种使用 案件。

##can 部分:(*)

Java 本身不支持宏。另一方面,您可以通过C 预处理器< /a>(简称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

##A better workaround:

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

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来过滤掉解决方案的“秘密”部分。这样我就可以维护参考解决方案,并轻松地重新生成代码框架。


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

You can but you shouldn't.

##The shouldn't part:

You shouldn't because using the pre-processor in that way is considered bad practice to start with, and there are better and more Java-idiomatic ways to solve this use case.

##The can part: (*)

Java itself doesn't support macros. On the other hand, you could pipe the source code through the C pre processor (CPP for short) just like the C/C++ compile chain does.

Here's a demo:

src/Test.java:

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

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

cpp command:

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

Result:

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

Compile:

$ javac preprocessed/Test.java

##A better workaround:

You can write your own utility class with a static method instead:

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

And when you want to use it, you can statically import the readInt method:

import static StdinUtil.readInt; 

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

(or do static import StdinUtil.STDIN; and use STDIN.nextInt().)

##And finally, an anecdote

I myself used the CPP preprocessing approach on Java code once! I was creating a programming assignment for a course. I wanted to be able to easily extract a code skeleton out of the reference solution. So I just used a few #ifdefs to filter out the "secret" parts of the solution. That way I could maintain the reference solution, and easily regenerate the code skeleton.


(*) Since I hate answering questions with "you shouldn't". Besides, some future reader may have good reasons for wanting to use the cpp in conjunction with Java sources!

夜未央樱花落 2024-11-25 03:27:27

不。 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();
   }
}

No. Java (the language) does not support macros of any sort.

However, certain constructs can be faked or wrapped. While the example is silly (why are you creating a new scanner each time!?!?!) the below shows how it can be achieved:

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

But much better:

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

Happy coding.


For comment:

Static methods can be called without needing an object to invoke them upon. However, in most cases one is already in an object. Consider:

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();
   }
}
他夏了夏天 2024-11-25 03:27:27

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

Java doesn't support macros simply because the designers of Java chose not to include that functionality. The longer answer is that Java doesn't have a preprocessor the way C/C++ does and cannot perform that functionality that the preprocessor normally would. The way I would implement this is simply create a wrapper class that wraps up the Scanner constructor calls. Perhaps something like

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

Or, better yet,

public class ScannerWrapper{
  private static Scanner instance = null;

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

   return instance.nextInt();
 }
一抹微笑 2024-11-25 03:27:27

Java 不支持宏。 IIRC,语言设计者认为宏和由此产生的预解析器是不必要且不受欢迎的复杂化。

使用函数代替:

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

其他地方:

Scanner input=new Scanner(System.in);

...


int a=readInt(input);

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

Java does not support macros. IIRC, the language designers felt that macros and the resultant preparser was an unnecessary and undesirable complication.

Use a function instead:

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

Elsewhere:

Scanner input=new Scanner(System.in);

...


int a=readInt(input);

Note also, that I create the scanner once and reuse it.

魔法少女 2024-11-25 03:27:27

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

If you want to use C-Style macros then someone has written a pre-processor http://www.slashdev.ca/javapp/ I have no idea how good it is though.

玉环 2024-11-25 03:27:27

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

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

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

There is no macro concept in Java. If you're doing that a lot, it's a bad idea to instantiate a new Scanner each time. Define a public static Scanner then reuse it each time:

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

// Somewhere in your code
YourClass.SCANNER.nextInt();
清音悠歌 2024-11-25 03:27:27

例如,您可以使用 Java Primitive Specializations Generator 来执行此操作:

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

...

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

You can do this, for example, with Java Primitive Specializations Generator:

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

...

int a = /* READINT */0/**/;
半暖夏伤 2024-11-25 03:27:27

宏是文本级预处理工具,如果设计不仔细,可能会被严重滥用。示例:

#define MULTIPLY( a, b ) ( a * b )

MULTIPLE(1+2,3+4) 的结果为 (1+2*3+4)

另一个示例

#define SQUARE( a ) ((a) * (a))

int x = 5;
SQUARE(x++);

将 x 增加两次。 ((x++) * (x++))

我认为 Java 语言设计者并没有因为这些原因而相信它,因为它意味着简单。

Macros are text-level pre-processing tools that can be badly abused if not carefully designed. Example:

#define MULTIPLY( a, b ) ( a * b )

MULTIPLE(1+2,3+4) will have the result of (1+2*3+4)

Another example

#define SQUARE( a ) ((a) * (a))

int x = 5;
SQUARE(x++);

will increment x twice. ((x++) * (x++))

I think that Java language designers did not buy it for these reasons, because it is meant to be simple.

冷了相思 2024-11-25 03:27:27

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

实用程序类:

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

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

Use a utility class and static import.

The utility class:

package my.utils;

public class ScannerUtils {
  private ScannerUtils() {}

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

Using the utility class:

package my.examples;

import static my.utils.ScannerUtils.*;

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

As others have said, you should probably cache your scanner, but that is a separate topic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文