Can I have macros in Java source files
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.
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 #ifdef
s to filter out the "secret" parts of the solution. That way I could maintain the reference solution, and easily regenerate the code skeleton.
This post has been rewritten as an article here.
(*) 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!
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();
}
}
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();
}
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.