到目前为止,我们使用的所有变量都是在方法main()的后面被声明。然而,Java允许变量在任何程序块内被声明。在第2章中已解释过了,程序块被包括在一对大括号中。一个程序块定义了一个作用域(scope)。这样,你每次开始一个新块,你就创建了一个新的作用域。你可能从先前的编程经验知道,一个作用域决定了哪些对象对程序的其他部分是可见的,它也决定了这些对象的生存期。
大多数其他计算机语言定义了两大类作用域:全局和局部。然而,这些传统型的作用域不适合Java的严格的面向对象的模型。当然将一个变量定义为全局变量是可行的,但这是例外而不是规则。在Java中2个主要的作用域是通过类和方法定义的。尽管类的作用域和方法的作用域的区别有点人为划定。因为类的作用域有若干独特的特点和属性,而且这些特点和属性不能应用到方法定义的作用域,这些差别还是很有意义的。因为有差别,类(以
及在其内定义的变量)的作用域将被推迟到第6章当讨论类时再来讨论。到现在为止,我们将仅仅考虑由方法或在一个方法内定义的作用域。
方法定义的作用域以它的左大括号开始。但是,如果该方法有参数,那么它们也被包括在该方法的作用域中。本书在第5章将进一步讨论参数,因此,现在可认为它们与方法中其他变量的作用域一样。
作为一个通用规则,在一个作用域中定义的变量对于该作用域外的程序是不可见(即访问)的。因此,当你在一个作用域中定义一个变量时,你就将该变量局部化并且保护它不被非授权访问和/或修改。实际上,作用域规则为封装提供了基础。
作用域可以进行嵌套。例如每次当你创建一个程序块,你就创建了一个新的嵌套的作用域。这样,外面的作用域包含内部的作用域。这意味着外部作用域定义的对象对于内部作用域中的程序是可见的。但是,反过来就是错误的。内部作用域定义的对象对于外部是不可见的。
为理解嵌套作用域的效果,考虑下面的程序:

// Demonstrate block scope.
class Scope { public static void main(String args[]) { int x; // known to all code within main x = 10; if(x == 10) { // start new scopeint y = 20; // known only to this block // x and y both known here. System.out.println("x and y: " + x + " " + y); x = y * 2; } // y = 100; // Error! y not known here // x is still known here. System.out.println("x is " + x);
}
}

正如注释中说明的那样,在方法main()的开始定义了变量x,因此它对于main()中的所有的随后的代码都是可见的。在if程序块中定义了变量y。因为一个块定义一个作用域,y仅仅对在它的块以内的其他代码可见。这就是在它的块之外的程序行y=100;被注释掉的原因。如果你将该行前面的注释符号去掉,编译程序时就会出现错误,因为变量y在它的程序块之外是不可见的。在if程序块中可以使用变量x,因为块(即一个嵌套作用域)中的程序可以访问被其包围作用域中定义的变量。变量可以在程序块内的任何地方被声明,但是只有在他们被声明以后才是合法有效的。
因此,如果你在一个方法的开始定义了一个变量,那么它对于在该方法以内的所有程序都是可用的。反之,如果你在一个程序块的末尾声明了一个变量,它就没有任何用处,因为没有程序会访问它。例如,下面这个程序段就是无效的,因为变量count在它被定义以前是不能被使用的。

// This fragment is wrong! count = 100;
// oops! cannot use count before it is declared!
int count;

另一个需要记住的重要之处是:变量在其作用域内被创建,离开其作用域时被撤消。
这意味着一个变量一旦离开它的作用域,将不再保存它的值了。因此,在一个方法内定义的变量在几次调用该方法之间将不再保存它们的值。同样,在块内定义的变量在离开该块时也将丢弃它的值。因此,一个变量的生存期就被限定在它的作用域中。
如果一个声明定义包括一个初始化,那么每次进入声明它的程序块时,该变量都要被重新初始化。例如,考虑这个程序:

// Demonstrate lifetime of a variable.
class LifeTime { public static void main(String args[]) { int x; for(x = 0; x < 3; x++) { int y = -1; // y is initialized each time block is entered System.out.println("y is: " + y); // this always prints -1 y = 100; System.out.println("y is now: " + y);
}
}
}

该程序运行的输出如下:

y is: -1
y is now: 100
y is: -1
y is now: 100
y is: -1
y is now: 100

可以看到,每次进入内部的for循环,y都要被重新初始化为-1。即使它随后被赋值为100,该值还是被丢弃了。
最后一点:尽管程序块能被嵌套,你不能将内部作用域声明的变量与其外部作用域声明的变量重名。在这一点上,Java不同于C和C++。下面的例子企图为两个独立的变量起同样的名字。在Java中,这是不合法的。但在C/C++中,它将是合法的,而且2个变量bar将是独立的。

v// This program will not compile
class ScopeErr { public static void main(String args[]) { int bar = 1; { // creates a new scope int bar = 2; // Compile-time error – bar already defined!
}
}
}

Java新职篇:变量的作用域和生存期相关推荐

  1. Java新职篇:声明一个变量

    变量是Java程序的一个基本存储单元.变量由一个标识符,类型及一个可选初始值的组合定义.此外,所有的变量都有一个作用域,定义变量的可见性,生存期.接下来讨论变量的这些元素. 声明一个变量 在Java中 ...

  2. Java新职篇:面向对象编程的3个原则是什么?

    所有面向对象的编程语言都提供帮助你实现面向对象模型的机制,这些机制是封装,继承及多态性.现在让我们来看一下它们的概念. 封装 封装(Encapsulation)是将代码及其处理的数据绑定在一起的一种编 ...

  3. Java新职篇:一维数组

    数组(array)是相同类型变量的集合,可以使用共同的名字引用它.数组可被定义为任何类型,可以是一维或多维.数组中的一个特别要素是通过下标来访问它.数组提供了一种将有联系的信息分组的便利方法. 一维数 ...

  4. Java新职篇:类型提升的约定

    除了将byte型和shorts型提升到int型以外,Java定义了若干适用于表达式的类型提升规则(type promotion rules).首先,如刚才描述的,所有的byte型和short型的值被提 ...

  5. Java新职篇:for循环

    你可能从先前的编程经验已经知道,在几乎所有的编程语言中,循环语句都是其重要组成部分.Java也不例外.事实上,你将在第5章中看到,Java提供了一套功能强大的循环结构.For循环也许是最通用的.如果你 ...

  6. Java新职篇:是什么是布尔型?

    Java有一种表示逻辑值的简单类型,称为布尔型.它的值只能是真或假这两个值中的一个.它是所有的诸如a<b这样的关系运算的返回类型.布尔类型对管理像if.for这样的控制语句的条件表达式也是必需的 ...

  7. java如何抽象一辆车,java新职篇:面向对象之抽象

    面向对象编程的一个实质性的要素是抽象.人们通过抽象(abstraction)处理复杂性. 例如,人们不会把一辆汽车想象成由几万个互相独立的部分所组成的一套装置,而是把汽车想成一个具有自己独特行为的对象 ...

  8. Java新职篇:使用程序块

    在Java中,可以将2个或2个以上的语句组成一组,这样的一组语句称为程序块(Codeblocks).程序块是通过将所属语句放在花括号中来实现.一旦创建了程序块,它就成为一个逻辑单元,可以作为一个单独的 ...

  9. Java新职篇:编译程序(2)

    要编译示例程序Example,须运行编译器程序javac,并在命令行上指定源程序文件名,格式如下所示: C:>javac Example.java 编译器javac产生了一个名为Example. ...

最新文章

  1. 参考答案:05 实对称矩阵与二次型
  2. 自定义本地Maven 仓库 配置
  3. ios 常用操作-1
  4. 使用TFS存储项目文档
  5. Table是怎样炼成的:HtmlTable
  6. 【NetApp】可以使用查设备备件型号的链接
  7. SqlServer分区表概述(转载)
  8. c++ 返回空对象_python中file对象的常用方法
  9. JDBC链接MySQL数据库
  10. 计算机网络管理员二级考试题,计算机网络管理员(二级)操作鉴定试题A
  11. miniprogram-ci官方文档
  12. IDEA Error occurred during initialization of VM
  13. 腾达ap设置说明_腾达(Tenda)F3无线信号放大模式(Client+AP)设置 | 192路由网
  14. hp ilo 服务器磁盘定位
  15. 电容0.1uF和104有什么区别?
  16. 机器学习技术:使用深度学习处理文本
  17. 【Windows】修改C盘用户名称
  18. unity shader 边缘光,内发光,外发光,轮廓边缘光,轮廓内边缘光,轮廓外边缘光
  19. apicloud学习笔记
  20. java调用ocr识别api_Java文字识别软件-调用百度ocr实现文字识别

热门文章

  1. [转载] python中numpy库的使用
  2. Vue.js 学习笔记 九 v-if和v-show
  3. 文件操作命令(TYPE)
  4. xx云网络实施方案案例
  5. (转)开发监控Linux 内存 Shell 脚本
  6. java异常处理和自定义异常利用try和catch让程序继续下去(回来自己再写个例子试运行下)...
  7. 【译】Input Method Manager (IMM):输入法管理器
  8. CV学习笔记-特征提取
  9. C++ Primer Plus学习(十四)——友元、异常和其他
  10. android多申请内存,Android内存等信息