1、静态成员的引入
当我们定义一个类,定义一个类的成员变量计数器count,定义一个类的构造函数
我们在构造函数内定义当调用构造函数的时候让count+1以获得构造函数被调用的次数
在这里我们实例化两次Test0类,于是调用了两次构造函数
但是输出结果显示两次的count值都是1
这是因为每次实例化都会初始化类中的count变量为0一次
那么我们怎么样才能使count只被初始化一次来记录下实例化的次数
答案是将count设置成静态变量 (count数据类型前 加static 关键字)
这次我们在执行一次 则count的值变成了构造函数的调用次数
那么static关键字为什么这么神奇呢?
2、深入理解静态成员
静态成员的定义:
静态成员的特点:
(1)静态成员是所有当前类的对象共享的
(2)类的静态成员是在类加载的时候申请分配空间的,静态成员贯穿整个应用程序的生命周期 (所以静态成员只在类加载时候初始化,之后再实例化的时候静态常量不会再初始化)
(3)静态成员只能访问类静态成员
例如在类内部定义一个方法,直接在类内部定义main函数想要调用这个方法则需要将这个方法设为静态的(因为main函数是静态的)
我们将show_count方法设置为静态成员 于是不再报错
(4) 静态成员可以在类实例化前通过类名直接访问
我们可以直接通过类名访问show_count静态方法
(5)静态成员方法没有this引用
那我们可以通过this引用访问(this指向当前类)show_count吗
显然不可以.
(5)非静态成员可以访问静态方法,静态方法不能访问非静态方法
3、静态块
静态块是java代码中,用static{}所括起来的部分;
这部分代码将在本类被“装载”时,首先被执行的代码,且只执行一次,且是线程单例安全。
在这类静态语句执行完成后,接着装载的就是静态成员,静态方法,构造方法和普通方法的导入。
转载于:https://www.cnblogs.com/youdiaodaxue16/p/7857752.html
如下输出体现了各块的具体执行顺序,并且静态块只执行一次
4、问题举例
以下的程序段,执行后会输出为什么呢?
为什么是2 1呢 我们先搞清楚顺序 1.先申请内存初始化静态变量(默认值)
2.从右向左给静态变量赋初值
在类加载时,静态变量按顺序申请内存,先初始化Test01对象 (默认为空)
再初始化默认值count1=0;count2=0
然后实例化对象调用构造函数
之后count1=1,count2=1
再执行赋值语句
使得count2=0
然后执行静态块
使得count1=2,count2=1
所以最后输出结果为 count1=2,count2=1
我们将静态语句的执行顺序换一下
将实例化静态对象放到 定义静态变量count2后面再执行主类
这次结果变为了2 2 与上次同理 按顺序执行静态语句 先为count1申请内存默认值为0,再为count2申请内存默认值为0
之后执行赋值语句
使得count2=0(本来就默认为0)
之后为实例化静态对象申请内存 对象值默认为空
再执行构造函数
此时count1=1, count2=1
再执行静态块
使得count1=2,count2=2
所以最后count1=2,count2=2
小练习:
答案是3
静态成员和全局成员的区别
-
定义和作用域:
- 静态对象:静态对象是通过使用
static
关键字在类级别上定义的。它们属于类而不是类的实例,并在类加载时初始化。静态对象可以在类的任何方法中访问,并且在整个应用程序的生命周期内保持一致。 - 全局对象:全局对象通常是在应用程序的某个全局作用域中定义的,如应用程序的上下文或全局变量。全局对象在应用程序启动时创建,并在整个应用程序中可被访问。
- 静态对象:静态对象是通过使用
-
访问方式:
- 静态对象:静态对象可以直接通过类名来访问,无需创建类的实例。在类中的任何方法中,可以通过
ClassName.staticMember
的形式访问静态成员。 - 全局对象:全局对象可以通过其定义的全局作用域来访问。在应用程序的任何地方,可以通过全局作用域或相应的标识符来访问全局对象。
- 静态对象:静态对象可以直接通过类名来访问,无需创建类的实例。在类中的任何方法中,可以通过
-
生命周期和存储方式:
- 静态对象:静态对象在类加载时创建,并在整个应用程序的生命周期内保持存在。它们通常存储在静态存储区中,不会被垃圾回收器回收,直到应用程序结束或类被卸载。
- 全局对象:全局对象在应用程序启动时创建,并在整个应用程序的生命周期内保持存在。它们可能存储在堆内存或其他全局存储区中,具体取决于应用程序的实现。
-
使用场景:
- 静态对象:静态对象适合用于表示与类关联的共享状态或共享行为。例如,全局配置、工具类、常量等可以定义为静态对象。
- 全局对象:全局对象适用于表示跨多个组件、模块或类共享的状态或数据。例如,全局数据库连接、用户会话管理器等可以定义为全局对象。