Java static关键字

简介

“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”
Java把内存分为栈内存和堆内存,其中栈内存用来存放一些基本类型的变量、数组和对象的引用,堆内存主要存放一些对象。在JVM加载一个类的时候,若该类存在static修饰的成员变量和成员方法,则会为这些成员变量和成员方法在固定的位置开辟一个固定大小的内存区域,有了这些“固定”的特性,那么JVM就可以非常方便地访问他们。同时如果静态的成员变量和成员方法不出作用域的话,它们的句柄都会保持不变。同时static所蕴含“静态”的概念表示着它是不可恢复的,即在那个地方,你修改了,他是不会变回原样的,你清理了,他就不会回来了。
同时被static修饰的成员变量和成员方法是独立于该类的,它不依赖于某个特定的实例变量,也就是说它被该类的所有实例共享。所有实例的引用都指向同一个地方,任何一个实例对其的修改都会导致其他实例的变化,实例如下:
public class User {
    private static int userNumber  = 0 ;
 
    public User(){
        userNumber ++;
    }
 
    public static void main(String[] args) {
        User user1 = new User();
        User user2 = new User();
 
        System.out.println("user1 userNumber:" + User.userNumber);
        System.out.println("user2 userNumber:" + User.userNumber);
    }
}    
Output:
user1 userNumber:2
user2 userNumber:2

用法

最基本的用法是,static 可以用于修饰成员变量和成员方法,我们将其称之为静态变量和静态方法,直接通过类名来进行访问。

当一个事物为static时,就意味着这个域或方法不会与包含它的那个类的任何对象实例关联在一起,所以从未创建某个类的任何对象,也可以调用其static方法或访问其static域。

变量

static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

static成员变量的初始化顺序按照定义的顺序进行初始化。


被static修饰的变量属于类变量,我们称之为静态变量,访问方式为:ClassName.propertyName

  • 静态变量是随着类加载时被完成初始化的,它在内存中仅有一个,且 JVM 也只会为它分配一次内存,同时类所有的实例都共享静态变量,即一处变、处处变,可以直接通过类名来访问它。

  • 但是实例变量则不同,它是伴随着new实例化的,每创建一个实例就会产生一个实例变量,它与该实例同生共死。

public class Test { private static int i = 0; public Test() {
        i++;
    } public static void main(String[] args) {
        Test t1 = new Test();
        Test t2 = new Test();
        System.out.println("test1:" + t1.i);
        System.out.println("test2:" + t2.i);
    }

}

输出结果:

test1:2 test2:2

分析:static声明的变量是共享的,类加载了两次,所以i变为了2。

所以我们一般在这两种情况下使用静态变量:对象之间共享数据、访问便捷。

方法

static修饰的方法我们称之为静态方法,我们通过类名对其进行直接调用。由于他在类加载的时候就存在了,它不依赖于任何实例,所以static方法必须实现,也就是说他不能是抽象方法abstract。
Static方法是类中的一种特殊方法,我们只有在真正需要他们的时候才会将方法声明为static。如Math类的所有方法都是静态static的。

但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。举个简单的例子:

在上面的代码中,由于print2方法是独立于对象存在的,可以直接用过类名调用。假如说可以在静态方法中访问非静态方法/变量的话,那么如果在main方法中有下面一条语句:

MyObject.print2();

此时对象都没有,str2根本就不存在,所以就会产生矛盾了。同样对于方法也是一样,由于你无法预知在print1方法中是否访问了非静态成员变量,所以也禁止在静态成员方法中访问非静态成员方法。而对于非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。因此,如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

另外记住,即使没有显示地声明为static,类的构造器实际上也是静态方法

局限

Static确实是存在诸多的作用,但是它也存在一些缺陷。
1、它只能调用static变量。
2、它只能调用static方法。
3、不能以任何形式引用this、super。
4、static变量在定义时必须要进行初始化,且初始化时间要早于非静态变量。
总结:无论是变量,方法,还是代码块,只要用static修饰,就是在类被加载时就已经”准备好了”,也就是可以被使用或者已经被执行,都可以脱离对象而执行。反之,如果没有static,则必须要依赖于对象实例。

版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。