实例变量
实例变量定义在类中但位于任何方法之外,并且只有在实例化类时才会被初始化。实例变量是属于每个唯一对象的字段。
例如,下面给的代码为employee对象的name、title和manager定义字段(实例变量) 。
上面的Employee类表示每个employee实例知道其自己的name、title和manage。换句话说,对于三个字段,每个实例都能够拥有它自己的唯一值。如果看到术语“字段” 、“实例变量”、"属性"(property)或”特性“(attribute),他们实际上是指同样的内容(这些属于之间实际上有一些微妙但有时又很重要的区别,但这些不会体现在考试中)。
对于考试,需要了解实例变量的如下要点:
- 可以使用4个访问级别中的任何一个(这意味着它们能够标识为3个访问修饰符中的任何一个) 。
- 可以标识为final。
- 可以标识为transient。
- 不能标识为abstract。
- 不能标识为synchronized。
- 不能标识为strictfp。
- 不能标识为native。
- 不能标识为static,否则会变成类变量。
前文已经介绍了将访问控制应用于实例变量的影响(其作用与对成员方法的作用相同) 。
本章稍后部分将介绍个将final 或 transient修饰符应用于变量意味着什么。首先,我们简单说明一项实例变量和局部变量之间的区别。下表比较了能够应用于方法和变量的修饰符。
局部变量 | 变量(非局部) | 方法 |
final | final public protected private static transient volatile | final public protectd private static abstract synchronized |
局部(自动/栈/方法) 变量
局部宾亮是在方法内声明的变量。这意味着变量不仅在方法内初始化,而且也在方法内声明。就像局部变量的生命周期从方法呢i开始一样,当方法完成时,局部变量也会被销毁。局部变量总是位于栈上,而不是位于堆上(第三章将更多地讨论栈和堆) 。尽管变量的值可能传递进另一个方法,该方法隋虎将值存储到实例变量中,但是,变量本省的生命周期只存在于该方法的范围内。
一定不要忘记,虽然局部变量位于栈上,但如果变量是对象引用,则该兑现本身仍然可以在堆上创建。不存在栈对象,只有栈变量。
局部变量声明不能使用可以应用于实例变量的多数修饰符,如public(或其他访问修饰符) 、transient、volatile、abstract或static。但是,如前所述,可将局部变量标识为final。第三章将会讲到(这里只是一个预览), 在使用局部变量之前必须用初始化它。例如:
通常在变量声明语句的同一行上初始化局部变量,尽管 在方法内可能还需要重新初始化它。关键是要记住,在试图使用局部变量之前,必须初始化它。编译器会拒绝试图使用未赋值的局部变量的任何代码,因为与实例变量不同,局部变量没有默认值。
不能在声明ubuntu变量的方法之外的任何代码中引用该局部变量。在上面个的代码示例中,在logIn()方法范围之外的任何地方引用变量count 都是不可能的。重申一遍,这并不是说count的值不能传递到该方法之外一获得新生。而是,只要方法完成就不能像下面的非法代码所演示的那样访问保存该值的变量count:
声明与实例变量同名的局部变量是可能的。这称作隐藏(shadowing) ,下面的代码演示了这一点:
上面的代码将输出:
local varable count is 10
instance variable count is 9
究竟威慑呢么要这样做呢?通常不会这样做。但是,比较常见的理由之一是:用与参数将要赋予的实例变量相同的名称命名该参数。
如下(错误的) 代码尝试用一个参数设置实例变量的值:
出于总体可读性考虑,因而决定将参数的名称命名为与被赋值的实例变量的名称相同,但是,怎样解决这种命名冲突?使用this关键字。this关键字永远、永远、永远会引用当前运行的对象。下面给的代码展示了这一点: