说我在C代码中有这样的东西。我知道你可以使用#define
代替,让编译器不能编译它,但出于好奇,我问的是编译器是否也会解决这个问题。
我认为这对Java编译器来说更为重要,因为它不支持#define
。
const int CONDITION = 0;
........
// Will the compiler compile this?
if ( CONDITION )
{
}
.......
答案 0 :(得分:21)
优化编译器可以实现语句x = 3;永不 执行并可以选择省略该语句的代码 生成的类文件,但语句x = 3;不被视为 在这里指定的技术意义上“无法到达”。
这种不同处理的理由是允许程序员 定义“标志变量”,例如:
static final boolean DEBUG = false;
然后编写如下代码:
if (DEBUG) { x=3; }
这个想法是应该可以改变DEBUG的值 从false到true或从true到false然后编译代码 正确,没有对程序文本进行其他更改。
不知道C。
答案 1 :(得分:11)
首先,Java不允许在C(if
,while
等条件句中使用非布尔值。另外,如果你的if
检查中有一个“常量”表达式,编译器会警告你正在比较相同的表达式,所以我确定它已经过优化。例如。
final int i = 1;
if (1 == i) { // warning
System.out.println("HI");
}
答案 2 :(得分:6)
而不是问这么简单的问题(唯一正确的答案是“用你的编译器试试”) - 为什么不尝试呢?
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
}
您无需了解java / c#字节码或汇编就能了解正在发生的事情。现在去尝试C#..
答案 3 :(得分:2)
我刚刚使用以下代码进行了快速检查
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
这意味着编译肯定会对静态最终值进行优化
答案 4 :(得分:0)
我可以回想一下我的Java和C#程序中的场景,它在哪里(优化它)。但我也知道这很大程度上取决于编译器设置 - 因此场景太不明确了。
在Java场景中,我们在一个Java源文件中使用了const值,而在另一个类(文件)中使用了它们。发生的事情是,当我们刚刚更改并使用const值重新编译文件时,使用部件的流程没有任何变化。我们不得不重新编译整个项目(这是它被优化的证据)。
答案 5 :(得分:0)
以下是 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
}
// ..
使用{}
声明清空if
:
const int i = 1;
// mov dword ptr [i], 1
if (i)
{
}
// ..
答案 6 :(得分:0)
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 ++编译器都会检测并优化掉这种类型的死代码。