¿Puedo tener macros en los archivos fuente de Java?

En mi progtwig, estoy leyendo números enteros de la consola muchas veces. Cada vez, necesito escribir esta línea.

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

Estoy acostumbrado a C / C ++ y me pregunto si puedo definir algo así como

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

y luego, en cada lugar de mi progtwig java, puedo leer la consola de formularios como

 int a = new READINT; 

Pero leo los libros de formularios Java no admite macros.

Alguien por favor explícame por qué es así, y puedo hacerlo de otra manera.

Puedes pero no deberías .

La parte no debe :

No deberías hacerlo porque usar el preprocesador de esa manera se considera una mala práctica para empezar, y hay mejores y más formas idiomáticas en Java para resolver este caso de uso.

La parte de la lata : (*)

Java en sí no admite macros. Por otro lado, puede canalizar el código fuente a través del preprocesador C (CPP, por sus siglas en inglés) tal como lo hace la cadena de comstackción C / C ++.

Aquí hay una demostración:

src/Test.java :

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

comando cpp :

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

Resultado:

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

Comstackr:

 $ javac preprocessed/Test.java 

Una mejor solución:

En su lugar, puede escribir su propia clase de utilidad con un método estático:

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

Y cuando quiera usarlo, puede importar de manera estática el método readInt :

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

(o realice una static import StdinUtil.STDIN; y use STDIN.nextInt() )

Y finalmente, una anécdota

¡Yo mismo usé el enfoque de preprocesamiento de CPP en el código de Java una vez! Estaba creando una asignación de progtwigción para un curso. Quería poder extraer fácilmente un esqueleto de código de la solución de referencia. Así que solo usé algunos #ifdef para filtrar las partes “secretas” de la solución. De esa manera podría mantener la solución de referencia y regenerar fácilmente el esqueleto del código.


Esta publicación ha sido reescrita como un artículo aquí .


(*) Ya que odio contestar preguntas con “no deberías”. Además, algún lector futuro puede tener buenas razones para querer usar el cpp junto con las fonts de Java.

No. Java (el idioma) no admite macros de ningún tipo.

Sin embargo, ciertos constructos pueden ser falsificados o envueltos. Si bien el ejemplo es tonto ( ¿por qué está creando un nuevo escáner cada vez?!!?! ) A continuación se muestra cómo se puede lograr:

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

Pero mucho mejor:

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

Feliz encoding.


Para comentarios:

Los métodos estáticos se pueden invocar sin necesidad de un objeto para invocarlos. Sin embargo, en la mayoría de los casos, uno ya está en un objeto . Considerar:

 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 no admite macros simplemente porque los diseñadores de Java decidieron no incluir esa funcionalidad. La respuesta más larga es que Java no tiene un preprocesador como lo hace C / C ++ y no puede realizar esa funcionalidad que normalmente tendría el preprocesador. La forma en que implementaría esto es simplemente crear una clase contenedora que finalice las llamadas al constructor del Scanner . Tal vez algo como

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

O mejor aún,

 public class ScannerWrapper{ private static Scanner instance = null; public static int readInt(){ if (instance == null){ instance = new Scanner(System.in); } return instance.nextInt(); } 

Java no admite macros. IIRC, los diseñadores de lengua sintieron que las macros y el preparador resultante era una complicación innecesaria e indeseable.

Use una función en su lugar:

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

En otra parte:

 Scanner input=new Scanner(System.in); ... int a=readInt(input); 

Tenga en cuenta también que creo el escáner una vez y lo vuelvo a usar.

Si quiere usar macros C-Style, alguien ha escrito un pre-procesador http://www.slashdev.ca/javapp/ No tengo ni idea de lo bueno que es.

No hay un concepto macro en Java. Si está haciendo eso mucho, es una mala idea crear instancias de un nuevo Scanner cada vez. Defina un Scanner público estático y Scanner utilizarlo cada vez:

 public class YourClass { public static final Scanner SCANNER= new Scanner(System.in); ... } // Somewhere in your code YourClass.SCANNER.nextInt(); 

Use una clase de utilidad e importación estática.

La clase de utilidad:

 package my.utils; public class ScannerUtils { private ScannerUtils() {} public static int readInt() { return new Scanner(System.in).nextInt(); } } 

Usando la clase de utilidad:

 package my.examples; import static my.utils.ScannerUtils.*; class Example { void foo() { int i = readInt(); } } 

Como han dicho otros, probablemente debería almacenar en caché su escáner, pero ese es un tema aparte.