O compilador otimizará isso?

Digamos que eu tenha algo assim em um código C. Eu sei que você pode usar um #define vez disso, para fazer o compilador não compilá-lo, mas apenas por curiosidade eu estou perguntando se o compilador também vai descobrir essa coisa.

Eu acho que isso é ainda mais importante para o Java Compiler, pois ele não suporta #define .

 const int CONDITION = 0; ........ // Will the compiler compile this? if ( CONDITION ) { } ....... 

em Java, o código dentro do if não fará parte do código compilado. Ele deve compilar, mas não será gravado no bytecode compilado. Na verdade, depende do compilador, mas não conheço um compilador que não o otimize. as regras são definidas no JLS :

Um compilador de otimização pode perceber que a instrução x = 3; nunca será executado e pode optar por omitir o código dessa declaração do arquivo de class gerado, mas a instrução x = 3; não é considerado “inacessível” no sentido técnico especificado aqui.

A justificativa para esse tratamento diferente é permitir que os programadores definam “variables ​​de sinalizador”, como:

 static final boolean DEBUG = false; 

e depois escrever código como:

 if (DEBUG) { x=3; } 

A idéia é que deve ser possível alterar o valor de DEBUG de false para true ou de true para false e, em seguida, compilar o código corretamente sem outras alterações para o texto do programa.

Não sei sobre C.

Primeiro, Java não permite não-booleano em condicionais como C ( if , while etc.). Além disso, se você tiver uma expressão “constante” em suas verificações if , o compilador avisará que você está comparando expressões idênticas, então estou certo de que está otimizada.

  final int i = 1; if (1 == i) { // warning System.out.println("HI"); } 

Em vez de fazer perguntas simples (onde a única resposta correta é “Experimente com o seu compilador”) – por que não tentar?

 public class Test { public static void main(String[] args) { if (true) { System.out.println("Yep"); } boolean var = false; if (var) { System.out.println("Nope"); } final boolean var2 = false; if (var2) { System.out.println("Nope"); } } } javac .\Test.java javap -c Test Compiled from "Test.java" public class Test { public Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String Yep 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: iconst_0 9: istore_1 10: iload_1 11: ifeq 22 14: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 17: ldc #3 // String Yep 19: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 22: return } 

Você não precisa saber muito sobre bytecode ou assembly java / c # para entender o que está acontecendo. E agora vá e tente o mesmo para C # ..

Acabei de fazer uma verificação rápida com o seguinte trecho de código

 public class Test { private static final boolean flag = true; public static void main(String[] args) throws InterruptedException { if(flag){ System.out.println("1"); System.out.println("1"); System.out.println("1"); System.out.println("1"); System.out.println("1"); System.out.println("1"); System.out.println("1"); System.out.println("1"); System.out.println("1"); } } } 

Quando flag = true, o tamanho do arquivo de class resultante é 708

quando flag = false. o tamanho do arquivo de class resultante é 462

o que implica que compilar certamente faz otimização para valores finais estáticos

Eu me lembro de cenários em meus programas Java e C #, onde funcionou (otimizar). Mas também sei que depende muito das configurações do compilador – portanto, o cenário é muito inespecífico.

Em um cenário Java, tínhamos os valores const em um arquivo de origem Java, enquanto eles eram usados ​​em outra class (arquivo). O que aconteceu foi que, quando acabamos de alterar e recompilamos o arquivo com os valores const, nada mudou no stream das partes em uso. Tivemos que recompilar todo o projeto (que é a prova de que foi otimizado).

Abaixo, é específico para a linguagem C. Eu não sei como o Java lida com isso.

Já que int é definido como const , if (i) se torna uma instrução no-op aqui. Um compilador inteligente deve ser capaz de otimizar essa instrução if vazia.

Exemplo : VC 2008

Um {} não vazio com a instrução if :

 const int i = 1; // mov dword ptr [i], 1 if (i) // mov eax, 1 // test eax, eax // je wmain+35h { int j = 2; // move dword ptr [j], 2 } // .. 

Vazio {} com a instrução if :

 const int i = 1; // mov dword ptr [i], 1 if (i) { } // .. 

Um compilador java deve detectar código obviamente inacessível, que é um requisito de linguagem. Portanto, o código a seguir será compilado sem erros:

 static final boolean flag = true; public static void main(String[] args) { final String msg; if (flag) msg = "true"; if (!flag) msg = "false"; System.out.println(msg); } 

Note que msg é final, mas o compilador não reclama que msg não foi inicializado nem reclama que é inicializado duas vezes. A maioria dos compiladores não grava código morto no arquivo de class. Mas mesmo que o JIT otimize isso.

C ++ também tem uma noção de constantes de tempo de compilation. Um const int é uma constante de tempo de compilation, portanto, ele pode ser usado como um argumento de modelo nontype, por exemplo. Portanto, todo compilador C ++ sensato detectará e otimizará o código obviamente ausente desse tipo, mesmo se você compilar sem especificar as opções de otimização.