55

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.

aioobe
  • 413,195
  • 112
  • 811
  • 826
Muthu Ganapathy Nathan
  • 3,199
  • 16
  • 47
  • 77
  • @Thomas Jungblut yes. setting up a new scanner is unnecessary only. Now only I saw that. but can I have a way in java to replace symbolic names as mentioned – Muthu Ganapathy Nathan Jun 29 '11 at 17:57
  • Wrapping in in a static method essentially does what you are asking. Regardless of whether it is a macro or not. Methods are the core part of Java, you cannot create symbolic names. – adamjmarkham Jun 29 '11 at 18:00
  • @AdamJMTech yes thank you. But can we create a library class which does this. (as the c++ compiler expands the object cin and links with system input) Thereby , every java developers get a more robust coding – Muthu Ganapathy Nathan Jun 29 '11 at 18:08
  • 1) http://manifold.systems/ https://github.com/manifold-systems/manifold 2) https://spoon.gforge.inria.fr/ https://github.com/INRIA/spoon – Dmytro Mitin Oct 22 '22 at 02:00

9 Answers9

171

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.


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!

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • 2
    why think out of the box if you actually know there is no box? :) – Aquarius Power Nov 17 '14 at 20:39
  • However, note that stylistic elements, such as personal preferences for indentation, newlines, etc. may be lost, so use this method to make a final product, not, instead, a program that you would like others to be able to read and understand with ease – axolotl Dec 01 '17 at 02:53
  • @Aalok, why would it be lost? `cpp` doesn't reformat the code. – aioobe Dec 01 '17 at 07:59
14

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

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();
 }
Chris Thompson
  • 35,167
  • 12
  • 80
  • 109
1

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.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
0

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

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

...

int a = /* READINT */0/**/;
leventov
  • 14,760
  • 11
  • 69
  • 98
0

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();
Michael Mior
  • 28,107
  • 9
  • 89
  • 113
Giann
  • 3,142
  • 3
  • 23
  • 33
0

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.

Greg Reynolds
  • 9,736
  • 13
  • 49
  • 60
0

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.

-1

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.

Dilum Ranatunga
  • 13,254
  • 3
  • 41
  • 52
  • why not to include this utility class in general java library installion to make it world wide. it will be more robust . am i correct – Muthu Ganapathy Nathan Jun 29 '11 at 18:11
  • From how I read your comment, you are wondering why such a method is not in core Java as a convenience API. There are many gaps in Java when it come to modeling common use cases conveniently. I don't have any perspective on whether this is such a case. – Dilum Ranatunga Jun 29 '11 at 18:22
  • ... but I want to add that designing such an API to satisfy the entire world would be tricky. For example, should there be a new scanner created each time? What happens if/when System.in is swapped out with a new InputStream -- keep using the old one or use the new one? – Dilum Ranatunga Jun 29 '11 at 18:25
  • Then for the efficient coding we have to use the traditional scan.nextInt() way only ya?. – Muthu Ganapathy Nathan Jun 29 '11 at 18:31
  • @Muthu, this is a good question, and not one to be stuck in a comment thread. You should ask a separate question about the right idiom for constructing and caching Scanners. – Dilum Ranatunga Jun 29 '11 at 19:21