局部类Local Classes
局部类是指定义在一个代码块block中的类,一组包含与{}
之内的一组语句。
本节包含了以下内容:
- 定义一个局部类Declaring Local Classes
- 访问所属类的成员Accessing Members of an Enclosing Class
- 局部类与内部类相似Local Classes Are Similar To Inner Classes
定义局部类Declaring Local Classes
你可以在任何代码块中定义局部类(参考 Expressions, Statements, and Blocks 表达式,语句代码块获取更多的信息).例如:你可以在一个方法体内,一个for
循环内或者一个if
语句中定义局部类。
下面的例子, LocalClassExample
,验证了两个电话号码。他在方法validatePhoneNumber
方法内定义了一个局部类PhoneNumber
:
|
|
这个例子通过两部验证一个电话号码,首先将电话号码中所有除了0-9的数字一处,然后检查电话号码是否包含了10个数字(北美的电话号码长度).例子的输出如下:
|
|
局部类访问你所处类的成员Accessing Members of an Enclosing Class
局部类有访问其所处类成员的权限。前面的例子中,PhoneNumber
构造器访问了成员 LocalClassExample.regularExpression
. 另外,局部类有访问局部变量的权限。不过,局部类只能访问被声明未final
的局部变量。当一个局部类访问一个局部变量或者时所处代码块的参数时,它捕获captures了那个变量或者参数。例如,PhoneNumber
构造器可以访问局部变量numberLength
因为他是定义未final
的;numberLength
是一个捕获变量captured variable.
然而你,Java SE 8开始,可以访问所属代码块中定义未final或者有效最终effectively final的变量以及参数.例如,假设变量numberLength
没有被声明为final
,并且在PhoneNumber
的构造其中加了如下的代码,将其变量值改变为数字7:
|
|
因为这个赋值语句,变量numberLength
就是不再时一个有效最终值。这样做的结果就是,当PhoneNumber
类尝试引用局部变量 numberLength
时, Java编译器生成一个错误信息,类似“local variable referenced from an inner class must be final or effectively final”(内部类中引用的局部变量必须是一个最终或或者一个等效最终值)
|
|
从Java SE 8开始,你再一个方法中定义局部变量时,他可以访问方法的参数。例如,你可以再局部类PhoneNumber
中定义如下方法:
|
|
方法printOriginalNumbers
方位了方法 validatePhoneNumber
的两个参数 phoneNumber1
以及phoneNumber2
。
局部类与遮蔽Shadowing and Local Classes
再局部类中声明一个类型(譬如变量)遮蔽其所在闭合范围内拥有相同名字的类型。参考遮蔽 Shadowing 获取更多信息。
局部类与内部类相似Local Classes Are Similar To Inner Classes
局部类与内部类相似,因为它们都不定义任何的静态static成员。局部类如果再静态方法内,譬如 PhoneNumber
类,定义再静态方法 validatePhoneNumber
中,就只能引用闭合范围内的静态成员。如果你不讲成员变量 regularExpression
定义为静态static,那么Java编译器就会生成一个错误, “non-static variable regularExpression
cannot be referenced from a static context.”(非静态变量regularExpression
不能再一个静态的上下文中引用)
局部类是非静态的,因为它可以方法所属闭合代码块中的实例变量。因此它们几乎不能包含任何类型的静态声明。
你不能再一个代码块中定义接口,因为接口再本质上静态的。例如,下面的代码引用是不能编译的因为接口HelloThere
被定义再方法greetInEnglish
方法体中:
|
|
你不能再一个局部类中定义静态的初始化器或者成员。以下的代码不能通过编译,因为方法 EnglishGoodbye.sayGoodbye
被声明为 static
. 当遇到这种方法定义时编译器会生成一个错误类似 “modifier ‘static’ is only allowed in constant variable declaration”(限定符static只能用再常量的声明上) :
|
|
局部类可以有静态成员除非时常量. (常量 constant variable是一个定义为final的基本数据类型或者String字符串类型的变量初始化为一个编译时的常量表达式。编译时常量表达式同时时一个字符串或者时编译时可以计算的运算表达式。参考理解成员变量Understanding Class Members 获取更多信息.) 以下代码摘绿可以通过编译,因为静态成员 EnglishGoodbye.farewell
是一个常量:
|
|