Java对象字段初始化使用什么?

12

对于 Object 类型,它是 null 吗?

class C {
    int i;
    String s;
    public C() {}
}

变量s会一直是null吗?

简单类型如int呢?会是什么呢?零还是一个任意值?

那么方法中的局部变量呢?

public void meth() {
    int i;
}

i的未初始化值是什么?


然而,仅依赖这种默认值通常被认为是不良的编程风格。

好的,你建议我们怎么做?

class A {
    String s = "";
    int i = 0;
}

或者:

class A {
    String s;
    int i;
    public A() {
        // default constructor
        s = "";
        i = 0;
    }
}

哪种更好,为什么?

6个回答

33

来源于sun的Java教程

在声明字段时不总是需要赋值。未初始化的字段将由编译器设置为合理的默认值。一般来说,这个默认值将为零或null,具体取决于数据类型。然而,依赖此类默认值通常被认为是不好的编程风格。

以下表格总结了上述数据类型的默认值。

Data Type   Default Value (for fields)
byte                    0 
short                   0   
int                     0 
long                    0L 
float                   0.0f 
double                  0.0d 
char                    '\u0000' 
boolean                 false
String (or any object)  null 

局部变量有些不同;编译器不会为未初始化的局部变量分配默认值。如果您无法在声明变量时初始化局部变量,请确保在尝试使用它之前为其赋值。访问未初始化的局部变量将导致编译时错误。


4
对于成员变量: String类型的默认值是null。原始数据类型的默认值为0(对于浮点数,为0.0)。
对于局部变量: 在使用局部变量之前,必须显式初始化它。
至于你问题的第二部分: 你可以在成员变量定义中始终写String s = "";,或者在构造函数中写s = "";。这样你就知道它将具有非空值。(另外,在setter方法中,你需要确保不允许将其设置回null。)

此外,在您的setter中,您需要确保没有人试图将其设置回null。大量愚蠢的工作。当然我可以做到。但这不是我对编程风格的期望。假设您必须为1000个字段执行此操作。 - EugeneP
你的态度怎么了?这就是在Java中所能做到的,而不依赖于第三方库(如nd的Google Collections答案所述),或者自己编写“检查null”的方法(或使用AOP或字节码操作或其他不良操作)。 - Ash
@Ash。感谢您的回答和评论。Google Collections看起来非常有趣。值得一试。 - EugeneP

3

字段:对象默认为null;int、long和short为0;字符串为null;布尔值为false。所有内容请参考此处

编译器会强制你自己初始化在方法中声明的变量,即局部变量


2

原始字段初始化为 0 / false。对象初始化为 null。但是,坦率地说,您可能已经尝试过这一点了。


3
尽管只有在确定的情况下尝试才有意义,但字段初始化是可靠且已定义的。当然,我们知道,在局部变量中,编译器不会让你走不确定的路。但是,如果您不确定并且不知道该去哪里寻找,那么提出问题并得到一个好答案都是值得的(顺便说一句,+1)。 - Andreas Dolk
2
坦白地说,你本可以尝试一下。 这可能是一个不可重复的测试。你可能会得到0分一千次。然后,当内存被刷新时,你可能会得到40亿分。 - EugeneP

1
关于setter方法的问题:setter的整个意义在于它们可以检查传递的对象是否符合类的要求。例如:
public void setS(String s) {
  if (s == null)
     throw new IllegalArgumentException("S must not be null");
  this.s = s;
}

或者,使用Google Collections/Google Guava:

public void setS(String s) {
  this.s = Preconditions.checkNotNull(s, "S must not be null");
}

当然,你可以定义任意的约束条件,例如:

/**
 * Sets the foo. Legal foo strings must have a length of exactly 3 characters.
 */
public void setFoo(String foo) {
  if (foo == null)
     throw new IllegalArgumentException("Foo must not be null");
  if (foo.length() != 3)
     throw new IllegalArgumentException("Foo must have exactly 3 characters");
  ...

当然,在这种情况下,您应该始终在setter和/或类的JavaDoc中声明属性的正确值范围。

preconditions.checkNotNull看起来非常漂亮!但为什么它不在标准Java库中呢?这是我对Java的期望。 - EugeneP

0

JLS 4.12.5. 变量的初始值

每个类变量、实例变量或数组组件在创建时都会初始化为默认值(§15.9,§15.10.2):
对于byte类型,默认值是零,即(byte)0的值。
对于short类型,默认值是零,即(short)0的值。
对于int类型,默认值是零,即0。
对于long类型,默认值是零,即0L。
对于float类型,默认值是正零,即0.0f。
对于double类型,默认值是正零,即0.0d。
对于char类型,默认值是空字符,即'\u0000'。
对于boolean类型,默认值是false。
对于所有引用类型(§4.3),默认值均为null。

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