《Java 7程序设计入门经典》一2.5 变量的作用域和生命周期

2.5 变量的作用域和生命周期

直至现在,我们使用的所有变量都在main()方法开始处声明。但是,Java允许在块内声明变量。正如第1章介绍的那样,块以左花括号开始,以右花括号结束。块定义一个作用域(scope)。于是,每次开始一个新块时,就创建一个新的作用域。作用域决定哪些对象对程序的其他部分可见。它还决定这些对象的生命周期。
许多其他计算机语言定义两种类型的作用域:全局作用域和局部作用域。尽管这对Java也勉强成立,但是这并不是对Java作用域进行分类的最好办法。Java最重要的作用域是由类和方法定义的作用域。本书在后面介绍类的时候,会讨论类(及其内部定义的变量)的作用域。现在只讨论定义在方法内部的作用域。
由方法定义的作用域以左花括号开始。但是,如果某个方法有形参,它也在方法的作用域内。
一般而言,在作用域内定义的变量对定义域外的代码是不可见的(即不可访问的)。于是,当在一个作用域定义一个变量时,就将变量限制在局部,防止非法访问和修改。作用域的规则事实上提供封装的基础。
作用域可以嵌套。例如,每次创建一个代码块时,就创建一个新的、嵌套的作用域。这时,外部作用域包括内部作用域。这意味着,在外部作用域中声明的对象在内部作用域中的代码仍然可见。但是,反之不然。在内部作用域中声明的对象在其外部不可见。
为了了解嵌套作用域的效果,请考虑以下程序:

正如注释所述,变量x在main()方法开始的作用域内,main()方法里所有后续代码可以访问它。在if块中声明变量y。由于块定义作用域,因此只有块内的其他代码才可见到变量y。这也是为什么注释掉块外的代码(行y=100)的原因。如果去掉该行前的注释符号,就会有编译错误。这是因为变量y在作用域外部。if块内部可以使用变量x,这是因为块内的代码(即嵌套作用域)可以访问作用域内声明的变量。
在块内,可以在任何地方声明变量,但只能在声明过后才有效。于是,如果在方法前声明变量,它对方法内的所有代码都有效。反之,若在块的末尾声明一个变量,由于没有代码可以访问它,因此它是毫无用处的。
另外还有一个要点:在进入作用域时创建变量,在作用域结束时销毁变量。这意味着,一旦出了作用域,变量就不再有其曾经的值。于是,在方法内声明的变量在各次调用间不能保存变量的值。同时,在块结束时,块中声明的变量就失去了它的值。于是,变量的作用域限制了其生命周期。
如果变量的声明包括初始化,在每次进入声明该变量的块时都会对变量初始化。例如,下面的程序:

程序输出如下所示:

可以看到,每次进入for循环时变量y初始化为-1。尽管曾经将值100赋予它,但是这个值丢失了。
Java还有一个令人惊奇的怪癖:尽管块可以嵌套,但是在内部作用域声明的变量不能和外部作用域声明的变量名字相同。例如,下面的程序试图声明两个名字相同的变量,它不能通过编译:

从这点看,其他语言(比如,著名的C和C++语言)对内部作用域中声明变量的名字就没有限制。所以,在C或C++中,外层for循环块内的count的声明是完全有效的,这样的声明会使外层变量不可见。Java的设计者认为这种机制很容易导致编程错误,所以不允许这么做。

时间: 2024-12-26 19:53:50

《Java 7程序设计入门经典》一2.5 变量的作用域和生命周期的相关文章

《Java 7程序设计入门经典》一导读

前 言 本书通过Java语言来讲解编程的基础知识.该书假设读者之前没有任何编程经验.本书首先介绍最基本的知识,例如,如何编译和运行Java程序:接着,讨论关键字.运算符和一些形成Java语言的构造.本书还会涉及Java的应用编程接口(Application Programming Interface,API)库.其中,包括Swing框架,它可以用来创建具有图形用户界面(Graphical User Interface,GUI)的程序.还包括集合框架,它可以用来存储对象集合.简而言之,本书旨在对J

《Java 7程序设计入门经典》一2.4 深入解析变量

2.4 深入解析变量 第1章介绍了变量.现在,我们来更详细地考查它们.如前所述,变量可以用以下形式声明: type var-name; 其中type变量的数据类型,var-name是变量名.可以声明任意有效类型的变量,包括之前描述的所有基本类型.在声明变量时,创建这种类型的一个实例.于是,变量的能力由类型决定.例如,boolean类型的变量可以用来存储真值或假值,但不能存储浮点值.另外,变量的类型在其生命周期内不能改变.例如,一个int变量不能变成char变量. Java中的所有变量必须先声明后

《Java 7程序设计入门经典》一1.16 Java中的标识符

1.16 Java中的标识符 在Java中,标识符是给方法.变量和其他用户定义的项的名字.标识符的长度可以是一个字符,也可以是多个字符.变量名可以由任意的字母.下划线或美元符号($)开始.后续字符可以是字母.数字.下划线和美元符号.下划线可以用来增加变量名的可读性,例如line_count.对Java而言,大写和小写是不同的.即,myvar和MyVar是两个单独的名字.下面是一些合法的标识符例子. 注意,标识符不可以以数字打头.例如,12x是无效的. 正如之前介绍的那样,不能使用关键字或保留字作

《Java 7程序设计入门经典》一1.4 Java语言

1.4 Java语言 本书使用Java语言来讲解编程的基础知识.虽然其他编程语言也可以用来达到此目的,但是由于以下两个原因,本书选择了Java:首先,它是世界上使用最广泛的计算机语言之一.所以从实际的观点看,它是绝佳的学习语言.其次,它设计和实现了一些特性,这些特性使得对编程基础知识的介绍变得简单. 但是还有第三个原因.Java展现了现代编程的许多特点.对Java的理解可以使你像专业程序员一样看待和思考编程工作.它是这个时代定义的语言之一. 计算机语言演进是一个正在进行的历史过程,而Java是其

《Java 7程序设计入门经典》一3.1 从键盘输入字符

3.1 从键盘输入字符 到目前为止,本书中的示例程序都向用户显示信息,但不从用户接收信息.于是,只使用了控制台输出,没有使用控制台输入(即键盘输入).主要原因在于,许多Java输入需要依赖和使用本书还未讲到的特性.这些特性在后面才会提及.另外,在真实情况下,许多Java程序和applet是图形界面或是窗口界面的,而不是控制台的.因此,本书的例子很少使用控制台输入.但是,有一种控制台输入相对容易使用,那就是从键盘读入字符.因为本章有许多需要用到这个特性的例子,所以在这里讨论它们. 我们将用Syst

《Java 7程序设计入门经典》一3.17 习题

3.17 习题 1.写一个程序,从键盘读入字符,直到接收到一个英文句号(.).程序需要计算输入的空格的个数.在程序结束时输出总结果. 2.请写出if-else-if梯队的一般形式. 3.针对下列程序 其中最后的else子句与哪个if配对? 4.写一个for循环语句,从1000计数到0,步进值为-2. 5.下面的代码片段是否有效? 6.请解释break语句的用途(包括其两种形式.) 7.在下面的代码片段中,break语句执行后会显示什么? 8.下面程序片段的输出是什么? 9.for循环中的迭代表达

《Java 7程序设计入门经典》一2.15 表达式

2.15 表达式 运算符.变量和字面量都是表达式(expression)的组成部分.当在程序中遇到表达式时,会计算该表达式.因为它在前面的程序中已经用过,所以读者可能对表达式已有相当的直观理解.另外,Java的表达式也与代数中的表达式类似.但是,现在还是要讨论表达式的一些方面. 2.15.1 表达式中的类型转换 在表达式中,可能将两种或多种不同类型但互相兼容的数据混合.例如,因为short类型和long类型都是数值类型,所以在表达式中将它们混合使用.当一个表达式中混合不同种类的数据,它们会转换为

《Java 7程序设计入门经典》一2.11 速记赋值运算符

2.11 速记赋值运算符 Java提供了特别的速记(shorthand)赋值运算符,用于简化一些赋值语句代码.让我们从一些例子开始了解速记赋值运算符.赋值语句: 相同.这两个语句都是将x的值减去100赋予变量x. 在Java中,速记运算符可以用于所有的二元运算符(即需要两个操作数的运算符).速记运算符的一般形式为: var op= expression; 于是,算术速记运算符和逻辑速记运算符有以下几种: 因为这些运算符将运算与赋值结合起来,它们正式的名称是复合赋值运算符(compound ass

《Java 7程序设计入门经典》一1.1 计算基础

1.1 计算基础 考虑到你正在修一门编程课程,你可能已经对计算科学的基础知识有了一定的了解.但是,不是所有人都有同样的知识,或某些知识可能是不准确的.为此,在介绍Java语言之前,先介绍计算科学中的一些核心概念.在这个过程中,本章会定义一些关键术语. 1.1.1 计算机的硬件组成 由于计算机最终会运行编写的程序,因此了解计算机各部分运行的基本方式是有帮助的.任意一台计算机都由一系列的部件组成,它们协同运作,形成一个计算机整体.尽管计算机组成的部件随着时间推移不断演进,但是计算机仍有许多共同的关键