Posso ter macros em arquivos de origem Java

No meu programa eu estou lendo inteiros formulário console muitas vezes. Toda vez, preciso digitar essa linha.

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

Eu estou acostumado a C / C ++ e eu estou querendo saber se eu posso definir algo como

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

e então, em todo lugar no meu programa java eu ​​posso ler o console do formulário como

 int a = new READINT; 

Mas eu li livros de formulários que o Java não suporta macros.

Alguém por favor me explique por que é assim, e eu posso fazer isso de qualquer outra forma.

Você pode, mas você não deveria .

A parte não deve :

Você não deveria porque usar o pré-processador dessa maneira é considerado uma prática ruim para começar, e há maneiras mais e mais idiomáticas para resolver esse caso de uso.

A parte da lata : (*)

O próprio Java não suporta macros. Por outro lado, você poderia canalizar o código-fonte através do pré-processador C (abreviado CPP) da mesma forma que a cadeia de compilation C / C ++.

Aqui está uma demonstração:

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 

Uma melhor solução alternativa:

Você pode escrever sua própria class de utilitário com um 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(); } } 

E quando você quiser usá-lo, você pode importar estaticamente o método readInt :

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

(ou faça a static import StdinUtil.STDIN; e use STDIN.nextInt() .)

E finalmente, uma anedota

Eu mesmo usei a abordagem de pré-processamento de CPP no código Java uma vez! Eu estava criando uma tarefa de programação para um curso. Eu queria ser capaz de extrair facilmente um esqueleto de código da solução de referência. Então eu usei apenas alguns #ifdef s para filtrar as partes “secretas” da solução. Dessa forma, eu poderia manter a solução de referência e regenerar facilmente o esqueleto do código.


Este post foi reescrito como um artigo aqui .


(*) Desde que eu odeio responder perguntas com “você não deveria”. Além disso, alguns futuros leitores podem ter boas razões para querer usar o cpp em conjunto com fonts Java!

Não. Java (a linguagem) não suporta macros de qualquer tipo.

No entanto, certas construções podem ser falsificadas ou agrupadas. Embora o exemplo seja tolo ( por que você está criando um novo scanner a cada vez! ), O abaixo mostra como isso pode ser alcançado:

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

Mas muito melhor:

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

Codificação feliz.


Para comentar:

Métodos estáticos podem ser chamados sem a necessidade de um object para invocá-los. No entanto, na maioria dos casos, um está em um object . 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 não suporta macros simplesmente porque os projetistas do Java optaram por não include essa funcionalidade. A resposta mais longa é que o Java não tem um pré-processador da maneira que o C / C ++ faz e não pode executar a funcionalidade que o pré-processador normalmente faria. A maneira de implementar isso é simplesmente criar uma class wrapper que encerre as chamadas de construtor do Scanner . Talvez algo como

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

Ou melhor ainda

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

Java não suporta macros. Segundo o IIRC, os projetistas da linguagem sentiram que as macros e o preparser resultante eram uma complicação desnecessária e indesejável.

Use uma function em vez disso:

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

Em outro lugar:

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

Note também que eu crio o scanner uma vez e reutilizo.

Se você quiser usar macros C-Style, então alguém escreveu um pré-processador http://www.slashdev.ca/javapp/ Eu não tenho idéia de como é bom.

Não há conceito de macro em Java. Se você está fazendo muito isso, é uma má idéia instanciar um novo Scanner cada vez. Defina um Scanner estático público e reutilize-o sempre:

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

Use uma class de utilitário e importação estática.

A class de utilidade:

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

Usando a class de utilitário:

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

Como outros já disseram, você provavelmente deveria armazenar seu scanner em cache, mas esse é um tópico separado.