¿Puedo tener macros en archivos fuente de Java?
(7)
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 C / C ++ hace y no puede realizar esa funcionalidad que normalmente lo haría el preprocesador. La forma en que implementaría esto es simplemente crear una clase de envoltorio que envuelva las llamadas del 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();
}
En mi programa estoy leyendo enteros desde 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 como
#define READINT Scanner(System.in).nextInt();
y luego, en cada lugar de mi programa java puedo leer la consola de formularios como
int a = new READINT;
Pero leí libros de formularios Java no soporta macros.
Alguien, por favor, explícame por qué es así, y puedo hacer esto de otra manera.
Java no soporta macros. IIRC, los diseñadores del lenguaje sintieron que las macros y el preparser resultante eran una complicación innecesaria e indeseable.
Utilice 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 reutilizo.
No hay concepto macro en Java. Si lo está haciendo mucho, es una mala idea crear una instancia de un nuevo Scanner
cada vez. Defina un Scanner
estático público y luego reutilícelo cada vez:
public class YourClass {
public static final Scanner SCANNER= new Scanner(System.in);
...
}
// Somewhere in your code
YourClass.SCANNER.nextInt();
Puedes pero no debes .
El no debería separarse:
No debería hacerlo porque el uso del preprocesador de esa manera se considera una mala práctica para comenzar, y existen formas mejores y más idiomáticas de Java para resolver este caso de uso.
La lata parte: (*)
Java en sí no admite macros. Por otro lado, podría canalizar el código fuente a través del preprocesador de C (CPP, por sus siglas en inglés) al igual que lo hace la cadena de compilació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());
}
}
Compilar:
$ javac preprocessed/Test.java
Una mejor solución:
Puede escribir su propia clase de utilidad con un método estático en su lugar:
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 estáticamente el método readInt
:
import static StdinUtil.readInt;
class Test {
public static void main(String[] args) {
int i = readInt();
}
}
(o realice static import StdinUtil.STDIN;
y utilice STDIN.nextInt()
.)
Y por último, una anécdota.
¡Yo mismo utilicé el enfoque de preprocesamiento de CPP en código Java una vez! Estaba creando una asignación de programació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
s 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 código del esqueleto.
Esta publicación ha sido reescrita como un artículo here .
(*) Ya que odio responder a las preguntas con "no deberías". Además, ¡algún futuro lector puede tener buenas razones para querer usar el cpp
junto con las fuentes de Java!
Si quieres usar macros de C-Style, alguien ha escrito un preprocesador http://www.slashdev.ca/javapp/ No tengo idea de lo bueno que es.
Utilice una clase de utilidad y la 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 guardar en caché su escáner, pero ese es un tema aparte.
No. Java (el lenguaje) no admite macros de ningún tipo.
Sin embargo, ciertas construcciones pueden ser falsificadas o envueltas. Si bien el ejemplo es tonto ( ¿por qué creas un nuevo escáner cada vez!?!?! ), El siguiente ejemplo 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 codificacion
Para comentarios:
Se pueden llamar métodos estáticos 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();
}
}