龙空技术网

不要再被Java中的成员变量和局部变量难倒了!这篇文章告诉你!

云端源想IT培训 67

前言:

此时朋友们对“静态变量的作用域”大概比较关怀,大家都需要分析一些“静态变量的作用域”的相关知识。那么小编在网上收集了一些关于“静态变量的作用域””的相关内容,希望姐妹们能喜欢,大家一起来学习一下吧!

“这里是云端源想IT,帮你轻松学IT”

嗨~ 今天的你过得还好吗?

幸与不幸都会有尽头的

平平安安就好

- 2023.08.18 -

成员变量和局部变量在每种编程语言中都有涉及,如果之前了解过其他语言的成员变量或者局部变量,那么在学习Java中的成员变量和局部变量时可以看看有哪些联系和不同,这一块的东西也不能说难,如果第一次接触可能会感觉有点乱,接下来小编就来详细给大家介绍成员变量和局部变量的相关知识。

一、Java变量介绍

首先我们来了解一下Java变量的分类、JVM中的主要内存空间的组成、三大变量的内存分布、以及栈区、堆区、方法区介绍和成员变量和局部变量的基本介绍。

Java变量的分类

JVM中的主要内存空间

三大变量内存分配情况

栈区、堆区、方法区介绍

栈区:存放各种方法(静态方法、实例方法、构造方法等)。ps:局部变量就在这些方法体中。

堆区:存放new出来的对象(实例)。

方法区:存放各个类,且静态变量在此初始化。

成员变量和局部变量的基本介绍

成员变量:在类中定义,用来描述对象将要有什么。局部变量:在类的方法中定义,在方法中临时保存数据。

下面就来详细介绍成员变量和局部变量以及它们的区别和使用:

二、成员变量

成员变量分为静态变量(类变量)和实例变量

静态变量有static修饰,它从该类的准备阶段就存在了,直到系统销毁这个类,静态变量的作用域与这个类的生存范围相同。

实例变量没有static修饰,它从该类的实例被创建时就存在,直到系统销毁这个实例,实例变量的作用域与对应实例的生存范围相同。

静态变量访问方法:通过类名访问,不需要创建实例;实例变量访问方法:通过实例访问,需要先new一个实例。

其实这里主要注意的还是静态变量。

这里主要说一下成员变量初始化时在内存中运行机制,先看一个代码:

public class MemoryShow {public static void main(String[] args) {Person p1 = new Person();Person p2 = new Person();Person.name = "李四";System.out.println("姓名:" + Person.name);System.out.println("p1年龄:" + p1.age);System.out.println("p2年龄:" + p2.age);}}class Person {//静态变量static String name = "张三";//实例变量int age;}

简单分析一下,当程序第一次执行Person类时,系统先加载这个类,并初始化这个类,在类的准备阶段,系统就为该类的类变量分配内存空间,并指定默认初始值(静态变量name也是在这个阶段完成了初始化);

然后接下来系统就在堆内存中为Person类分配了一块内存区,且为age默认赋值为0;然后生成了Person对象,并通过引用变量p1指向该对象;

当再次执行Person类时,已经不需要再为Person类初始化了,所以直接生成了Person对象,通过p2指向它。

三、局部变量

局部变量相对成员变量就没有那么复杂了,先分别介绍一下局部变量中的三种不同形式:

形参: 在定义方法签名时定义的变量,形参的作用域在整个方法内有效。方法局部变量: 在方法体中定义的变量,作用域从定义该变量的地方生效,到该方法结束时失效。代码块局部变量: 在代码块中定义的变量,作用域从定义该变量的地方生效,到该代码块结束时失效。

和成员变量不同的一点是:局部变量除了形参外,都需要显式初始化,就是指定一个初始值,否则无法访问。

局部变量在内存中的运行机制:

因为局部变量需要显式初始化,所以系统不会对它进行初始化,即系统并没有给局部变量分配内存空间,只有它赋值后,系统才会分配内存将该值放入其中;

因为局部变量不属于任何对象或者类,所以它存放在栈内存中,且栈内存的变量不需要系统垃圾回收,因为它们会随着方法或者代码块运行结束而结束;所以局部变量只保存基本类型或者对象的引用(引用变量),所以局部变量占用内存比较小。

Java语法允许局部变量和成员变量重名,但是如果在一个方法里,局部变量会覆盖成员变量;如果想要在该方法里访问成员变量,就需要通过**this引用(针对实例变量)或者类名(针对静态变量)**作为调用者来限定访问成员。

看一个代码就明白了:

public class RepeatTest {// 静态变量(类变量)static String name = "张三";// 实例变量int age = 18;public static void main(String[] args) {// 局部变量 和静态变量name = "张三"重名String name = "李四";// 因为静态变量name被这里的局部变量覆盖,所以输出为“李四”System.out.println("姓名:" + name);// 这时候如果想要调用静态变量可以使用类来调用//不能用this调用的原因是:main方法是静态方法System.out.println("姓名:" + RepeatTest.name);// 调用test方法new RepeatTest().test();}public void test() {// 局部变量 和实例变量age = 18重名int age = 666;// 因为实例变量name被这里的局部变量覆盖,所以输出为“666”System.out.println("年龄:" + age);// 这时候如果想要调用实例变量可以使用this调用System.out.println("年龄:" + this.age);}}

但是,最好从现在开始就要养成良好的编程习惯,在写代码时不要出现局部变量和成员变量重名的情况。

四、成员变量和局部变量的区别

1)作用域不同

局部变量的作用域仅限于定义它的方法;成员变量的作用域在整个类内部都是可见的。

2)初始值不同

成员变量有默认的初始值;局部变量没有默认的初始值,必须自行设定初始值。

3)存储位置不同

成员变量是在对象创建以后存在于堆中,对象回收时,成员变量消失;局部变量是在方法被调用时存在于栈中,方法调执行结束,从栈中清除。

4)生命周期不同

对象的创建而创建,对象回收时,成员变量消失;随着方法的调用被创建,方法执行结束,从栈中清除。

五、变量的使用

说了这么多,可能你已经晕了,但是这些变量归根结底我们了解它们就是为了用它们,那什么时候用局部变量,什么时候用成员变量呢?

我们先看三个代码:

public class ScopeTest01 {//静态变量(类成员变量)//再次强调一下这里为什么定义静态变量而不是实例变量//因为main方法是静态方法,不需要对象只通过类调用,而实例变量必须有对象才能调用static int i;public static void main(String[] args) {for (i = 0; i < 5; ++i) {System.out.println("Hello World!!!");}}}

public class ScopeTest02 {public static void main(String[] args) {//局部变量int i;for (i = 0; i < 5; ++i) {System.out.println("Hello World!!!");}}}

public class ScopeTest03 {public static void main(String[] args) {// 代码块局部变量for (int i = 0; i < 5; ++i) {System.out.println("Hello World!!!");}}}

这三个代码的运行结果都是一样的,而它们分别用了成员变量和局部变量,结果都一样,那我们就需要看看那种方法是最好的了。

首先,ScopeTest01 使用的是成员变量,我们都知道成员变量存在于堆内存中,且只有类销毁时或者实例销毁时它才销毁,这就将作用域扩大到类存在范围或者实例存在范围,作用域的扩大有两个坏处:

增加了变量的生存时间,会导致更大的内存开销扩大了变量的作用域,不利于提高程序的内聚性

同理可以对比ScopeTest02 和 ScopeTest03,最后可总结出 ScopeTest03 最符合规范。

所以定义变量的时候要尽可能的保证作用范围最小,这样可以很好的提高程序的性能,包括局部变量。

考虑使用成员变量有四种情况:

如果定义的变量需要描述对象的信息,且每个对象都有可能不同,那么用成员变量中的实例变量;

如果定义的变量所描述的信息对这个类的所有对象都相同,那么类相关的信息就定义为成员变量中的静态变量;

如果某个类中需要一个变量保存该类或者实例运行时的状态信息,该变量定义为成员变量;

如果某个信息需要在类的多个方法之间共享,则该信息使用成员变量。

总结:成员变量和局部变量大概主要内容就是这些了,看完可能还是有点乱,一定要多看几遍,自己总结一下。这些都是学习Java的基础内容,这都搞不清的话,那么之后一会一个静态变量,一会一个局部变量都把你搞晕了。并且想要用Java写出来好代码,就必须了解这些内容,这将会在你未来的开发中起到重要作用!

我们下期再见!

END

文案编辑|云端学长

文案配图|云端学长

内容由:云端源想分享

标签: #静态变量的作用域 #静态变量的作用域是整个类 #java的成员变量是什么