Java static

在总结完 想知道Java代码执行顺序么,Let's go 一文后,对 Java 中的static关键字有了更深的理解,所以有兴趣的可以先看看这篇文章。

前言

Java中没有c、c++这类语言中的全局变量的概念,但是可以通过使用static关键字修饰变量,获得一个类似于全局变量的静态变量。在 Java中,static意为“静态”。可以用来修饰变量、代码块和方法。

static 变量

Java中有两类变量:类变量和实例变量。
*** 类变量: ***被static关键字修饰的变量为类变量、静态变量,JVM 在类的连接阶段,会为类变量赋予默认的初始值,在类初始化阶段,赋予类变量程序中指定的初始化值。类变量伴随着类的产生而产生,类的卸载而消失。所以,在整个类的生命周期中,类变量都只会被初始化一次,并且类变量独立于类的实例而存在,为类的所有实例所共享。
类变量可以直接通过类名来使用,而无需创建该类对象。
*** 实例变量: ***未被static修饰的变量即为实例变量,实例变量与具体的类对象有关,随着对象的实例化而产生,对象的终结而消失。

** 类变量 VS 实例变量 **

  • JVM 只会为类变量分配一次内存,而每创建一个实例,JVM 就会为实例变量分配一次内存;
  • 类变量的生命周期一般比实例变量长;
  • 类变量为类的所有实例所共享,而实例变量只与特定的实例有关;
  • 既可以直接使用类名.类变量的方式使用类变量,也可以使用对象.类变量的方式使用类变量,但实例变量只能通过实例访问;

一般会在如下两种情况下使用类变量:在对象之间共享值时和为了方便访问变量时

static块

被static关键字修饰的代码块为静态块,静态块一般用于初始化静态变量,静态块不存在于任何方法体内,可以放在类的任何地方,也可以有多个。当 Java类初始化时,会执行静态块中的代码,静态块和静态域的初始化顺序依程序中定义的顺序而定--** 先定义则先执行 **

static 方法

被static修饰的方法为静态方法。

  • 静态方法独立于任何实例,可以直接通过类名引用;
  • 静态方法内部不能够引用非静态域和非静态方法,因为静态方法独立于类的实例而存在,而非静态方法/非静态域依赖于类的特定实例,与某一个实例密切相关,当一个类实例对象终结时,与之相关的非静态域和方法也都随之消失,所以如果一个静态方法内部引用了一个非静态域/方法的话,此时就会出错;
  • 静态方法内部不能使用 this 和 super 关键字,因为这两个关键字均是与类的实例相关的;

Q & A:

*** Q: ***main 方法为什么设计成static方法?
*** A: ***这是出于效率考虑,将 main 方法设计为 static 的,便可以在类初始化工作完成后就使用该方法,而无需等到创建一个对象后;其次,可以节省内存,因为 static 方法只会占据一份内存,而非 static 的方法则会在每次实例化时均分配内存
*** Q: ***static和final一起使用,会产生什么效果?
*** A: ***static final一般用于表示常量,如果用static final修饰变量,则表示该变量一旦赋值,则不能够再修改它的值(或它指向的对象引用),并且该变量独立于任何实例,可以直接通过类访问;static final 修饰的方法是一个静态的、不能被修改的方法。

示例

public class staticTest {
    private static A statica = new A("private static");
    public static A staticb = new A("public static");
    private static final A STATIC_C = new A("private static final");
    public static final A STATIC_D = new A("public static final");

    public int a = 8;

    static {
        print("static block in staticTest");
        // a++; 提示 non-static field 'a' cannot be referenced from a static context
    }

    static void staticMethod(){
        print("static method in staticTest");
        // a++; 提示 non-static field 'a' cannot be referenced from a static context
    }
}
public class staticMain {

    public static void main(String[] args) {
        staticTest.staticMethod();      // 直接通过类名访问静态方法
        print(staticTest.staticb);      // 直接通过类名访问静态变量
        print(staticTest.STATIC_D);

        // staticTest.a; 提示 non-static field 'a' cannot be referenced from a static context
        // 非静态方法必须通过实例访问
        staticTest test = new staticTest();
        print(test.a);
    }
}
// Output:
private static
public static
private static final
public static final
static block in staticTest
static method in staticTest
class A & the str is public static
class A & the str is public static final
8

你可能感兴趣的:(Java static)