大多数程序设计语言都提供了“作用域”(Scope)的概念。
在Java中,作用域决定了变量的“可见性”和“生存时间”。Java中的作用域是有花括号{}
来决定的。
先来看一段代码:
1 | public class Scope{ |
上面的例子中,由于int a = 1
这行代码已经在最外部的作用域中声明a
变量,所以在内部的作用域是不可以再重新声明a
了,只能拿到a
这个变量来进行使用,这是Java中强制规定的,而在C和C++中是允许的,因为Java的设计者认为这样会造成混淆。
再来看一个例子:
1 | public class Scope{ |
看到有什么不同了吗?我们把int a = 1
这行代码放到了内部作用域的下方了,此时是允许的。由于int a = 2
是定义在作用域里面,当超过作用域时,这块的内存空间会自动从栈中移除,并且同一块作用域的变量的“可见性”是只能在当前作用域及它的子作用域可见。由于int a = 1
已经超出了该作用域,所以可以再次声明一个a
变量。
再来看一个例子来理解下:
1 | public class Scope{ |
执行结果:
1 | a |
Java对象不具备与基本类型数据一样的存在时间。用new关键字创建一个Java对象的时候,它会超出作用域的范围之外。
对象的作用域
1 | public class Scope{ |
上面的 str
变量会在作用域外消失,但是 new String()
出来的对象是不存在栈中的,它存在堆中,并且不会随着作用域而消失。它随后会由Java垃圾回收器进行释放,垃圾回收器会查找用new
所创建的所有对象,并判断其中哪些对象不再被变量引用,从而释放内存以便新的对象存储。
总结
在同一作用域范围下的成员变量和局部变量是可以变量名相同的,在同一个作用域下和子作用域的局部变量则不允许变量名相同,在方法中使用变量的时候假如不指明使用成员变量还是局部变量,那么默认的就是使用成员变量,但是如果在方法中重新定义了一个和成员变量相同的局部变量,那么就会默认使用局部变量,并且在该作用域下的该变量都是使用局部变量,一旦超出该作用域,如果不指定,默认还是使用成员变量的。