Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 编译器会对此进行优化吗_Java_C_Optimization - Fatal编程技术网

Java 编译器会对此进行优化吗

Java 编译器会对此进行优化吗,java,c,optimization,Java,C,Optimization,假设我在C代码中有类似的东西。我知道你可以用一个#define来代替,让编译器不编译它,但出于好奇,我问编译器是否也会解决这个问题 我认为这对于Java编译器更为重要,因为它不支持#define const int CONDITION = 0; ........ // Will the compiler compile this? if ( CONDITION ) { } ....... 首先,Java不允许C等条件中使用非布尔值(if,while等)。此外,如果您的中有一个“常量”表达式,

假设我在C代码中有类似的东西。我知道你可以用一个
#define
来代替,让编译器不编译它,但出于好奇,我问编译器是否也会解决这个问题

我认为这对于Java编译器更为重要,因为它不支持
#define

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

}
.......

首先,Java不允许C等条件中使用非布尔值(
if
while
等)。此外,如果您的
中有一个“常量”表达式,如果
检查,编译器将警告您正在比较相同的表达式,因此我确信它已优化

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

在Java中,if中的代码甚至不会成为已编译代码的一部分。它必须编译,但不会写入已编译的字节码。它实际上取决于编译器,但我不知道有哪种编译器不会对其进行优化。规则定义如下:

优化编译器可能会意识到,语句x=3;永远不会 可以选择从中省略该语句的代码 生成的类文件,但语句x=3;不被视为 此处规定的技术意义上的“无法达到”

这种不同处理的基本原理是允许程序员 定义“标志变量”,例如:

然后编写如下代码:

if (DEBUG) { x=3; }
其思想是,应该可以更改DEBUG的值 从false到true或从true到false,然后编译代码 正确无需对程序文本进行其他更改


不了解C。

我能回忆起Java和C程序中的场景,它在哪里(优化了它)。但我也知道它在很大程度上取决于编译器设置——因此场景太不具体了


在Java场景中,我们在一个Java源文件中使用const值,而在另一个类(文件)中使用它们。发生的事情是,当我们只是用const值更改并重新编译文件时,使用部分的流程没有任何更改。我们必须重新编译整个项目(这就是它被优化的证据).

与其问这么简单的问题(唯一正确的答案是“用你的编译器试试”),为什么不试试呢

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."<init>":()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
}
公共类测试{
公共静态void main(字符串[]args){
如果(真){
System.out.println(“是”);
}
布尔值var=false;
if(var){
系统输出打印号(“Nope”);
}
最终布尔值var2=false;
if(var2){
系统输出打印号(“Nope”);
}
}
}
javac.\Test.java
javap-c测试
从“Test.java”编译而来
公开课考试{
公开考试();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:getstatic#2//Field java/lang/System.out:Ljava/io/PrintStream;
3:ldc#3//字符串是
5:invokevirtual#4//方法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 yes
19:invokevirtual#4//方法java/io/PrintStream.println:(Ljava/lang/String;)V
22:返回
}

你不需要了解太多关于java/c字节码或汇编的知识,就可以理解正在发生的事情。现在,你可以尝试同样的方法来处理c。

下面是针对c语言的。我不知道java如何处理它

由于
int
被定义为
const
if(i)
在这里成为
no op
指令。智能编译器应该能够优化掉空的
if
语句

示例:VC 2008

带有
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
}
// ..
const int i = 1;
// mov dword ptr [i], 1
if (i)
{
}
// ..
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
}
// ..
const int i = 1;
// mov dword ptr [i], 1
if (i)
{
}
// ..

我只是用下面的代码快速检查了一下

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");        
        }

    }

}
当flag=true时,生成的类文件大小为708

当flag=false时。生成的类文件大小为462


这意味着compile肯定会对静态最终值进行优化

java编译器必须检测明显不可访问的代码,这是一种语言要求。因此,以下代码将编译无误:

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);
}
请注意,msg是最终版本,但编译器既不会抱怨msg未初始化,也不会抱怨它已初始化两次。大多数编译器不会向类文件写入死代码。但即使如此,JIT也会将其优化


C++还具有编译时常数的概念。const int是编译时常数,因此它可以用作非类型模板参数。因此,每个明智的C++编译器都会检测并优化这种类型的死区代码,即使编译时没有指定优化选项。

为什么不试试看,重新查看一下。生成二进制代码?具体来说,您可以在类上使用javap-c命令打印出字节码,这实际上非常容易阅读。我记得看到
if(false){…}
作为Java中排除代码的推荐方法,在C预处理器中使用a la
#if
。那是几年前的事了。@Joe和我从未理解过这种吸引力。在任何现代IDE上,注释几行代码都比编写if()快更清楚的是。我有一个糟糕的习惯——只有在手头没有好的IDE时才需要。@Voo——如果你有很多块应该一起禁用,可能分布在所有类中呢?仅仅更改一个常量的值肯定会更快,更不容易出错。(但我也不喜欢这个想法)这是用标准JDK1.6T实现的吗