Подтвердить что ты не робот

Могу ли я иметь макросы в исходных файлах Java

В моей программе я много раз читаю целые формы консоли. Каждый раз мне нужно набрать эту строку.

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

Я привык к C/С++, и мне интересно, могу ли я определить что-то вроде

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

а затем, в любом месте в моей программе java, я могу читать консоль формы как

int a = new READINT;

Но я читал книги форм. Java не поддерживает макросы.

Кто-нибудь, пожалуйста, объясните мне, почему это так, и могу ли я сделать это любым другим способом.

4b9b3361

Ответ 1

Вы можете, но не должны.

Не должен расставаться:

Вы не должны этого делать, потому что использование препроцессора таким способом считается плохой практикой, и существуют лучшие и более идиоматические способы решения этого варианта использования.


Может часть: (*)

Сама Java не поддерживает макросы. С другой стороны, вы можете передавать исходный код через пре-процессор C (для краткости 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().)


И, наконец, анекдот

Я сам однажды использовал подход предварительной обработки CPP для кода Java! Я создавал задание по программированию для курса. Я хотел иметь возможность легко извлечь фрагмент кода из эталонного решения. Поэтому я просто использовал несколько #ifdef чтобы отфильтровать "секретные" части решения. Таким образом, я мог бы поддерживать эталонное решение и легко восстанавливать скелет кода.


Этот пост был переписан как статья здесь.


(*) Так как я терпеть не могу отвечать на вопросы с "ты не должен".Кроме того, у некоторых будущих читателей могут быть веские причины хотеть использовать cpp вместе с cpp Java!

Ответ 2

Нет. 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();
   }
}

Ответ 3

Java не поддерживает макросы просто потому, что разработчики Java решили не включать эту функциональность. Более длинный ответ заключается в том, что Java не имеет препроцессора, как это делает 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();
 }

Ответ 4

Java не поддерживает макросы. IIRC, разработчики языка считали, что макросы и полученный препарат являются ненужным и нежелательным осложнением.

Используйте вместо этого функцию:

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

В другом месте:

Scanner input=new Scanner(System.in);

...


int a=readInt(input);

Обратите внимание, что я создаю сканер один раз и повторно его использую.

Ответ 5

В Java нет концепции макроса. Если вы делаете это много, плохая идея каждый раз создавать новый Scanner. Определите общедоступный статический Scanner затем используйте его каждый раз:

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

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

Ответ 6

Если вы хотите использовать макросы C-Style, тогда кто-то написал предварительный процессор http://www.slashdev.ca/javapp/ Я понятия не имею, насколько это хорошо хотя.

Ответ 7

Вы можете сделать это, например, с помощью Java Primitive Specializations Generator:

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

...

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

Ответ 8

Используйте класс утилиты и статический импорт.

Класс утилиты:

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

Как говорили другие, вы, вероятно, должны кэшировать свой сканер, но это отдельная тема.