Java static的常见问题和使用误区

学完《Java static关键字》一节我们可能会产生很多疑问,所以本节主要讲解学习 Java 中关于 static 常见的几个问题。

1)为什么要用”static“关键字?
通常来说,用 new 创建类的对象时,数据存储空间才被分配,方法才供外界调用。有时候我们只想为特定域分配单一存储空间,不考虑要创建多少对象或者说根本就不创建任何对象,有时候我们想在没有创建对象的情况下也想调用方法。在这两种情况下,static 关键字,满足了我们的需求。

2)”static“关键字是什么意思?Java 中是否可以覆盖(子类中如果创建了一个与父类中相同名称、相同返回值类型、相同参数列表的方法,只是方法体中的实现不同,以实现不同于父类的功能,这种方式被称为方法重写,又称为方法覆盖。这里了解即可,教程后面我们会详细讲解)一个 private 或者是 static 的方法?

“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。

Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编译时静态绑定的。static 方法跟类的任何实例都不相关,所以概念上不适用。

3)是否可以在 static 环境中访问非 static 变量?
static 变量在 Java 中是属于类的,它在所有的实例中的值是一样的。当类被 Java 虚拟机载入的时候,会对 static 变量进行初始化。如果你的代码尝试不用实例来访问非 static 的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。

4)static 静态方法能不能引用非静态资源?
不能,new 的时候才会产生的东西,对于初始化后就存在的静态资源来说,不能引用它。

5)static 静态方法里面能不能引用静态资源?
可以,因为都是类初始化的时候加载的。

6)非静态方法里面能不能引用静态资源?
可以,非静态方法就是实例方法,那是 new 之后才产生的,那么属于类的内容它都认识。

使用误区

1)static 关键字会改变类中成员的访问权限吗?
有些初学者会将 Java 中的 static 与 C/C++ 中的 static 关键字的功能混淆了。在这里只需要记住一点,与 C/C++ 中的 static 不同,Java 中的 static 关键字不会影响到变量或者方法的作用域。在 Java 中能够影响到访问权限的只有 private、public、protected、friendly 这几个关键字。看下面的例子就明白了:

定义一个 Student 类,代码如下:

public class Student 
{
    public static String name = "张三";
    private static int age = 10;
}

定义 Main 类调用 Student 类的 age 属性,代码如下:

public class Main 
{
    public static void main(String[] args) 
    {
        System.out.println(Student.name);
        System.out.println(Student.age);
    }
}

代码第 4 行会提示错误“Student.age 不可视(The field Student.age is not visible)”,这说明 static 关键字并不会改变变量和方法的访问权限。 

2)能通过 this 访问静态成员变量吗?
虽然对于静态方法来说没有 this,那么在非静态方法中能够通过 this 访问静态成员变量吗?先看下面的一个例子,这段代码输出的结果是什么? 

public class Main 
{
    static int value = 33;

    public static void main(String[] args) throws Exception 
    {
        new Main().printValue();
    }

    private void printValue() 
    {
        int value = 3;
        System.out.println(this.value);    // 输出 33
    }
}

这里面主要考察 this 和 static 的理解。this 代表什么?this 代表当前对象,那么通过 new Main() 来调用 printValue 的话,当前对象就是通过 new Main() 生成的对象。而 static 变量是被对象所享有的,因此在 printValue 中的 this.value 的值毫无疑问是 33。在 printValue 方法内部的 value 是局部变量,根本不可能与 this 关联,所以输出结果是 33。在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。  

3)static 能作用于局部变量么?
在 C/C++ 中 static 是可以作用域局部变量的,但是在 Java 中切记,Java 语法规定 static 是不允许用来修饰局部变量。