web-dev-qa-db-fra.com

Puis-je avoir des macros dans les fichiers source Java

Dans mon programme, je lis plusieurs fois la forme sous forme de console. Chaque fois, je dois taper cette ligne.

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

Je suis habitué au C/C++ et je me demande si je peux définir quelque chose comme

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

puis, à chaque endroit de mon programme Java je peux lire la console de formulaire comme

int a = new READINT;

Mais je lis les livres de formulaires Java ne prend pas en charge les macros.

Quelqu'un, s'il vous plaît, expliquez-moi pourquoi il en est ainsi, et puis-je le faire d'une autre manière.

47

Vous pouvez mais vous ne devriez pas.

La partie ne devrait pas:

Vous ne devriez pas parce que l'utilisation du préprocesseur de cette façon est considérée comme une mauvaise pratique pour commencer, et il existe des moyens meilleurs et plus idiomatiques pour résoudre ce problème cas d'utilisation.


La partie peut: (*)

Java lui-même ne prend pas en charge les macros. D'un autre côté, vous pouvez diriger le code source via le C pré processeur (CPP pour faire court) tout comme la chaîne de compilation C/C++ le fait.

Voici une démo:

src/Test.Java:

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

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

cpp commande:

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

Résultat:

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

Compiler:

$ javac preprocessed/Test.Java


Une meilleure solution de contournement:

Vous pouvez écrire votre propre classe utilitaire avec une méthode statique à la place:

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

Et lorsque vous souhaitez l'utiliser, vous pouvez importer de manière statique la méthode readInt:

import static StdinUtil.readInt; 

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

(ou faites static import StdinUtil.STDIN; et utilisez STDIN.nextInt().)


Et enfin, une anecdote

J'ai moi-même utilisé l'approche de prétraitement CPP sur Java une fois! Je créais une affectation de programmation pour un cours. Je voulais pouvoir extraire facilement un squelette de code de la solution de référence. J'ai donc J'ai juste utilisé quelques #ifdef pour filtrer les parties "secrètes" de la solution. De cette façon, je pouvais maintenir la solution de référence et régénérer facilement le squelette du code.


Ce message a été réécrit en tant qu'article ici .


(*) Puisque je déteste répondre aux questions avec "tu ne devrais pas". En outre, certains futurs lecteurs peuvent avoir de bonnes raisons de vouloir utiliser le cpp en conjonction avec Java sources!

143
aioobe

Non. Java (la langue) ne prend en charge aucune macro.

Cependant, certaines constructions peuvent être truquées ou enveloppées. Bien que l'exemple soit stupide ( pourquoi créez-vous un nouveau scanner à chaque fois!?!?! ) ce qui suit montre comment cela peut être réalisé:

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

Mais beaucoup mieux:

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

Codage heureux.


Pour commentaire:

Les méthodes statiques peuvent être appelées sans avoir besoin d'un objet pour les invoquer. Cependant, dans la plupart des cas, on est déjà dans un objet . Considérer:

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

Java ne prend pas en charge les macros simplement parce que les concepteurs de Java ont choisi de ne pas inclure cette fonctionnalité. La réponse plus longue est que Java n'a pas de préprocesseur le façon C/C++ fait et ne peut pas exécuter cette fonctionnalité que le préprocesseur ferait normalement. La façon dont j'implémenter cela est simplement de créer une classe wrapper qui termine les appels du constructeur Scanner. Peut-être quelque chose comme

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

Ou, mieux encore,

public class ScannerWrapper{
  private static Scanner instance = null;

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

   return instance.nextInt();
 }
2
Chris Thompson

Java ne prend pas en charge les macros. IIRC, les concepteurs de langage ont estimé que les macros et le pré-produit résultant étaient une complication inutile et indésirable.

Utilisez plutôt une fonction:

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

Autre part:

Scanner input=new Scanner(System.in);

...


int a=readInt(input);

Notez également que je crée le scanner une fois et le réutilise.

1
Lawrence Dol

Vous pouvez le faire, par exemple, avec Java Primitive Specializations Generator :

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

...

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

Si vous voulez utiliser des macros de style C, alors quelqu'un a écrit un pré-processeur http://www.slashdev.ca/javapp/ Je n'ai aucune idée de sa qualité.

0
Greg Reynolds

Il n'y a pas de concept de macro en Java. Si vous faites cela souvent, c'est une mauvaise idée d'instancier un nouveau Scanner à chaque fois. Définissez une statique publique Scanner puis réutilisez-la à chaque fois:

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

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