使用默认初始化和不初始化有区别吗?

4

有没有这样的情况,使用默认初始化,比如:

int myValue;

或者

MyObject o = null;

如果我不初始化变量,与我初始化变量的情况相比,会改变程序的行为吗?

我正在寻找一个示例。


3
如果您在谈论类字段,那么不会。什么样的例子? - BalusC
1
我在谈论类字段和局部变量。如果有的话,这可能会改变程序行为的示例。 - anon
4个回答

8
本地变量在使用之前必须初始化,这是由编译器强制执行的。
字段默认情况下会被初始化为与其类型相关联的默认值(false、0、null),这是Java语言规范所要求的。
因此,将其显式初始化为默认值只会增加大量无用信息。
MyObject o = null;

不做任何超出

MyObject o;

2
int val = 0; 生成的字节码作为字段的长度与 int val; 不同,因此似乎存在某些差异。 - Flexo
字节码有所不同,但在语义上没有任何变化。就像执行 a = 1; a = 1; a = 1; 等同于执行 a = 1; - JB Nizet
当然有差别,它很微小并且略显牵强,但是非常真实 - 请参考我的示例,特别是字节码的反汇编(我在发表评论时没有查看它)。 - Flexo

3

当初始化发生的时间不同时,就会出现差异,例如以下示例。这有点牵强,但问题在于初始化发生的时间。

考虑以下类:

import java.lang.reflect.Field;

public class base {
  protected base(int arg) throws Exception {
    Field f = getClass().getDeclaredField("val");
    System.out.println(f.get(this));
    f.set(this, 666);
  }
}

以下是两个扩展该类的类。test1 明确设置为0:
public class test1 extends base {
  int val=0; // Explicitly set to 0

  public test1() throws Exception {
    super(0);
  }

  public static void main(String argv[]) throws Exception {
    System.out.println(new test1().val);
  }
}

test2 只是留下它:

public class test2 extends base {
  int val; // just leave it to be default

  public test2() throws Exception {
    super(0);
  }

  public static void main(String argv[]) throws Exception {
    System.out.println(new test2().val);
  }
}

运行这些代码会得到以下结果:
javac test1.java && java test1                        
0
0

但对于第二种情况:
javac test2.java && java test2                        
0
666

这很好地展示了不同的行为,唯一的变化是字段中的= 0。原因可以通过反汇编第一个案例来看到:
import java.io.PrintStream;

public synchronized class test1 extends base
{
    int val;

    public test1()
        throws Exception
    {
        super(0);
        val = 0; // Note that the the explicit '= 0' is after the super()
    }

    public static void main(String astring[])
        throws Exception
    {
        System.out.println(new test1().val);
    }
}

如果这对你的代码库有影响,那么你需要担心的事情更多!

也没有反射:public class Main { abstract static class Base implements Runnable { protected Base() { run(); } } static class DerivedExplicitDefault extends Base { int val = 0; public void run() { val = 666; } } static class DerivedImplicitDefault extends Base { int val; public void run() { val = 666; } } public static void main(String argv[]) throws Exception { System.out.println(new DerivedExplicitDefault().val); System.out.println(new DerivedImplicitDefault().val); } } - Tim Carson

1
在Java中,类的实例和静态成员字段被赋予默认值:原始类型默认为0,对象默认为null,布尔类型默认为false。
然而,在Java中,局部变量必须在使用之前在方法作用域内声明并赋值,否则会报错。这种变量没有默认值。

0
据我所知,不存在这种情况。Java规范要求变量根据以下规则进行默认初始化:

数字:0或0.0
布尔值:false
对象引用:null

只要你按照这些规则编程,显式地初始化为上述相同的值不会改变程序的行为。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接