Java中未初始化的类成员不会发出任何编译器错误.然而局部变量呢.为什么?

Lio*_*ion 18 java

请考虑Java中的以下代码段.它不会编译.

package temppkg;

final public class Main
{
    private String x;
    private int y;

    private void show()
    {
        String z;
        int a;

        System.out.println(x.toString()); // Causes a NullPointerException but doesn't issue a compiler error.
        System.out.println(y); // Works fine displaying its default value which is zero.
        System.out.println(z.toString()); // Causes a compile-time error - variable z might not have been initialized.
        System.out.println(a); // Causes a compile-time error - variable a might not have been initialized.
    }

    public static void main(String []args)
    {
        new Main().show();
    } 
}
Run Code Online (Sandbox Code Playgroud)

为什么在上面的代码片段中声明的类成员(x和y)不会发出任何编译时错误,即使它们没有显式初始化并且只需要初始化局部变量?

Pau*_*aul 23

如有疑问,请检查Java语言规范(JLS).

介绍中你会发现:

第16章描述了语言确保在使用前明确设置局部变量的精确方式.虽然所有其他变量都自动初始化为默认值,但Java编程语言不会自动初始化局部变量,以避免屏蔽编程错误.

16章第一段指出,

当对其值的任何访问发生时,每个局部变量和每个空白最终字段必须具有明确赋值.一个Java编译器必须执行特定的保守流分析,以确保每次访问局部变量或空白最终字段f,f在访问之前是明确分配的; 否则必须发生编译时错误.

默认值本身在4.12.5节中.该部分打开时:

每个类变量,实例变量或数组组件在创建时都使用默认值进行初始化.

...然后继续列出所有默认值.

JLS实际上并不难理解,我发现自己越来越多地使用它来理解Java为什么会这样做......毕竟,这是Java圣经!

  • "如有疑问,请查看Java语言规范(JLS)." 我认为这对一些绝对的初学者来说不是一个好建议.一本书或一些文章将是一个更好的建议.但答案很棒.+1. (7认同)