Java基础之静态变量和实例变量以及局部变量的区别

注:有需要的可以进一步关注Java中关于 [4]8.2. Class Members

在Java中,变量([1]Declaring Member Variables[2]Variables )包括以下几种:

  • 成员变量,包括静态变量和实例变量,是在类中定义的,通过 static 关键字区分,也称为属性 field局部变量 local variables:方法中定义的临时变量
  • 静态变量/类变量, class variables (or static variables),属于类,类加载时会同时进行加载,只有唯一的一份。
  • 实例变量 instance variables:属于实例,实例化时会都会初始化一次,是实例独有的。
  • 局部变量 local variables:方法中定义的临时变量
  • 方法参数:方法定义中的参数列表中涉及到的变量

以下是一些相关的总结:

比较点

静态变量/类变量

实例变量

局部变量

语法定义

在类中声明且使用 static 关键词修饰的变量称为静态变量(static variables),

也称为类变量(class variables),还可以用访问权限修饰符和final修饰

和类变量声明类似,区别在于没有 static 修饰

 

定义位置

在类中,但是在方法、构造器、语句块之外,声明上是独立存在的

一样

方法内部、构造器或者语句块中(静态代码块和非静态代码块)

存放位置

方法区

堆 (不包括栈上分配、标量替换等)

栈 + 堆(对象)

加载时机

类加载时进行唯一的一次内存分配,除非类加载器重新加载,

否则不会再分配内存,在类加载器层面只有这一个共享的

实例化的时候分配内存

语句执行时(声明+初始化/赋值)进行分配

运行时/生命周期

与类绑定,随着类加载而初始化,随着类卸载而回收。静态变量是类层面的,

只要类加载器加载了对应的类,静态变量就已经分配内存了,也即是说,在

加载类的过程中完成静态变量的内存分配,而且只有一次。静态变量不用创

建任何实例对象可以被直接使用,在类加载器层面是唯一的,所有实例共享,

一般是直接通过类名来进行引用。

实例变量随着对象的实例化创建而分配,随着对象的消失而回收。实例变量是类实例层面的,

是具体实例的一个属性,只有类实例化分配内存后才会存在,才可以通过实例对象的引用来

进行访问使用。每次实例化都会新分配一次内存,实例变量依赖于对应的具体实例,而且在

每个实例对象中是唯一的,不共享。

一般随着方法调用结束而销毁,除非作为结果返回或者中间作为外层变量的属性等,生命周期会扩大

作用域

类加载时就存在,类卸载时回收

实例化时存在,随着实例被回收而消失

对应的语句块内部,一般是在最近的{}内部

调用方式

一般通过类名直接引用,如 ClassName.StaticVariableName

通过实例对象进行引用

在作用域之内直接引用,一般建议哪里使用就在哪里声明

可见性

public/(default)/protected/private (访问权限修饰符)

一样

/

final修饰

一般都当作是全局常量,而且建议全大写的命名方式

只初始化一次,后续不能再修改(对象不能重新引用,原始数据类型不能修改值),当作是引

用值(内部属性可能可以修改)或者原始数据类型值不可变

同样只能初始化一次

初始化/默认值

数值型变量默认值为 0,布尔型默认值为 false null

一样

无默认值,需要强制初始化

共享和并发问题

静态变量是共享的,多线程写会存在并发问题,建议尽量使用不可变对象或者常量

实例独有,有可能存在并发修改问题

 

使用建议

静态常量、不可变对象

 

哪里用到就在哪里声明

 

参考: