静态变量、静态方法和实例变量、实例方法的区别联系

static(掌握)

11.3.1static 概述

static 是java 语言中的关键字,表示“静态的”,它可以用来修饰变量、方法、代码块等, 修饰的变量叫做静态变量,修饰的方法叫做静态方法,修饰的代码块叫做静态代码块。在 java 语言中凡是用static 修饰的都是类相关的,不需要创建对象,直接通过“类名”即可访问,即使使用“引用”去访问,在运行的时候也和堆内存当中的对象无关。
本小节要求大家主要掌握:什么时候将变量定义为静态变量?什么时候把方法定义为静态方法?静态代码块什么时候使用?类体中的代码有执行顺序要求吗?空引用访问静态变量和静态方法会出现空指针异常吗?

11.3.2静态变量

java 中的变量包括:局部变量和成员变量,在方法体中声明的变量为局部变量,有效范围很小,只能在方法体中访问,方法结束之后局部变量内存就释放了,在内存方面局部变量存储 在栈当中。在类体中定义的变量为成员变量,而成员变量又包括实例变量和静态变量,当成员 变量声明时使用了 static 关键字,那么这种变量称为静态变量,没有使用 static 关键字称为实例变量,实例变量是对象级别的,每个对象的实例变量值可能不同,所以实例变量必须先创建 对象,通过“引用”去访问,而静态变量访问时不需要创建对象,直接通过“类名”访问。实 例变量存储在堆内存当中,静态变量存储在方法区当中。实例变量在构造方法执行过程中初始 化,静态变量在类加载时初始化。那么变量在什么情况下会声明为静态变量呢?请看以下代码, 定义一个“男人”类:

public class Man {
//身份证号int idCard;
//性别(所有男人的性别都是“男”)
//true 表示男,false 表示女
boolean sex = true; public Man(int idCard){
this.idCard = idCard;
}
}
public class ManTest {
public static void main(String[] args) { Man jack = new Man(100);
System.out.println(jack.idCard + "," + (jack.sex ? "男" : "女"));
Man  sun = new Man(101);
System.out.println(sun.idCard + ","  + (sun.sex ? "男" : "女")); Man cok = new Man(102);
System.out.println(cok.idCard + "," + (cok.sex ? "男" : "女"));
}
}

运行结果如下图所示:

在这里插入图片描述

我们来看一下以上程序的内存结构图:

在这里插入图片描述

“男人类”创建的所有“男人对象”,每一个“男人对象”的身份证号都不一样,该属性 应该每个对象持有一份,所以应该定义为实例变量,而每一个“男人对象”的性别都是“男”, 不会随着对象的改变而变化,性别值永远都是“男”,这种情况下,性别这个变量还需要定义 为实例变量吗,有必要让每一个“男人对象”持有一份吗,这样岂不是浪费了大量的堆内存空 间,所以这个时候建议将“性别=男”属性定义为类级别的属性,声明为静态变量,上升为“整 个族”的数据,这样的变量不需要创建对象直接使用“类名”即可访问。请看代码:

public class Man {
//身份证号int idCard;
//性别(所有男人的性别都是“男”)
//true 表示男,false 表示女
static boolean sex = true;
public Man(int idCard){
this.idCard = idCard;
}
}
public class ManTest {
public static void main(String[] args) {
 Man jack = new Man(100);
System.out.println(jack.idCard + "," + (Man.sex ? "男" : "女"));
Man  sun = new Man(101);
System.out.println(sun.idCard + "," + (Man.sex ? "男" : "女"));
Man cok = new Man(102);
System.out.println(cok.idCard + "," + (Man.sex ? "男" : "女"));
}
}

运行结果如下图所示:

在这里插入图片描述

我们来看一下以上程序的内存结构图:

在这里插入图片描述

通过以上内容的学习我们得知,当一个类的所有对象的某个“属性值”不会随着对象的改 变而变化的时候,建议将该属性定义为静态属性(或者说把这个变量定义为静态变量),静态 变量在类加载的时候初始化,存储在方法区当中,不需要创建对象,直接通过“类名”来访问。如果静态变量使用“引用”来访问,可以吗,如果可以的话,这个访问和具体的对象有关系吗? 来看以下代码:

public class ManTest {
public static void main(String[] args) {
//静态变量比较正式的访问方式System.out.println("性别 = " + Man.sex);
//创建对象
Man jack = new Man(100);
//使用“引用”来访问静态变量可以吗? 
System.out.println("性别 = " + jack.sex);
//对象被垃圾回收器回收了
jack = null;
//使用“引用”还可以访问吗?
System.out.println("性别 = " + jack.sex);
}
}

运行结果如下图所示:
在这里插入图片描述

通过以上代码以及运行结果可以看出,静态变量也可以使用“引用”去访问,但实际上在 执行过程中,“引用”所指向的对象并没有参与,如果是空引用访问实例变量,程序一定会发 生空指针异常,但是以上的程序编译通过了,并且运行的时候也没有出现任何异常,这说明虽 然表面看起来是采用“引用”去访问,但实际上在运行的时候还是直接通过“类”去访问的。静态方法是这样吗?请看以下代码:

public class Man {
//身份证号int idCard;
//性别(所有男人的性别都是“男”)
//true 表示男,false 表示女
static boolean sex = true; 
public Man(int idCard){
this.idCard = idCard;
}
//静态方法
public static void printInfo(){
System.out.println("-----"+ (Man.sex ? "男" : "女")  + "	");
}
}
public class ManTest {
public static void main(String[] args) {
//静态变量比较正式的访问方式
System.out.println("性别 = " + Man.sex);
//创建对象
Man jack = new Man(100);
//使用“引用”来访问静态变量可以吗?
 System.out.println("性别 = " + jack.sex);
//对象被垃圾回收器回收了
jack = null;
//使用“引用”还可以访问吗?
System.out.println("性别 = " + jack.sex);
//静态方法比较正式的访问方式
Man.printInfo();
//访问静态方法可以使用引用吗?并且空的引用可以吗?
jack.printInfo();
}
}

运行结果如下图所示:

在这里插入图片描述

通过以上代码测试得知,静态变量和静态方法比较正式的方式是直接采用“类名”访问, 但实际上使用“引用”也可以访问,并且空引用访问静态变量和静态方法并不会出现空指针异常。实际上,在开发中并不建议使用“引用”去访问静态相关的成员,因为这样会让程序员困惑,因为采用“引用”方式访问的时候,程序员会认为你访问的是实例相关的成员。
总之,所有实例相关的,包括实例变量和实例方法,必须先创建对象,然后通过“引用” 的方式去访问,如果空引用访问实例相关的成员,必然会出现空指针异常。所有静态相关的, 包括静态变量和静态方法,直接使用“类名”去访问。虽然静态相关的成员也能使用“引用” 去访问,但这种方式并不被主张。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不熬夜,早点睡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值