Java基础(012):静态变量和实例变量以及局部变量的区别

注:有需要的可以进一步关注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 一样 无默认值,需要强制初始化
共享和并发问题 静态变量是共享的,多线程写会存在并发问题,建议尽量使用不可变对象或者常量 实例独有,有可能存在并发修改问题  
使用建议 静态常量、不可变对象   哪里用到就在哪里声明

 

参考: