局部类是指那些被定义在块中的类,在大括号中由0条或者多条语句组成。典型的,你可以发现定义在一个方法体的局部类。
这节覆盖如下内容:
- 定义局部类
- 访问封装类中的成员
- 覆盖局部类
局部类和内部类相似
定义局部类
你可以在任何块中定义一个局部类。例如,你可以再一个方法体重、一个for循环中、一个if语句块中。
下面例子,LocalClassExample,校验两个电话号码,在方法validatePhoneNumber中定义局部类PhoneNumber:
public class LocalClassExample{
static String regularExpression = "[^0-9]";
public static void validatePhoneNumber(String phoneNumber1,String phoneNumber2){
final int numberLength = 10;
class PhoneNumber{
String formattedPhoneNumber = null;
PhoneNumber(String phoneNumber){
String currentNumber = phoneNumber.replaceAll(regularExpression,"");
if(currentNumber.length()==numberLength){
formattedPhoneNumber=currentNumber;
}else{
formattedPhoneNumber=null;
}
}
public String getNumber(){
return formattedPhoneNumber;
}
}
PhoneNumber myNumber1 = new PhoneNumber(phoneNumber1);
PhoneNumber myNumber2 = new PhoneNumber(phoneNumber2);
if(myNumber1.getNumber() == null){
System.out.println("First number is invalid");
}else{
System.out.println("First number is "+myNumber1.getNumber());
}
if(myNumber2.getNumber() == null){
System.out.println("Second number is invalid");
}else{
System.out.println("Second number is"+myNumber2.getNumber());
}
}
public static void main(String... args){
validatePhoneNumber("123-456-7890","456-7890");
}
}
结果:
First number is 1234567890
Second number is invalid
访问封装类中的成员
一个局部类有权限访问封装类中的成员。在前面的例子中,PhoneNumber构造方法访问LocalClassExample.regularExpression。
另外,一个局部类也可以访问局部变量。然而,一个局部类只能访问那些被定义为final的局部变量。当一个局部变量访问一个局部变量或者封装块中参数,它可以捕获到变量或者参数的值。例如,PhoneNumber构造函数访问了局部变量numberLength,因为它被声明为final;numberLength是一个捕获的变量。
然而,从Java8开始,一个局部类可以访问局部变量和块中参数,不管局部变量是final还是非final的。一个变量或者参数的值在被初始化后就不会再被修改。比如,如果变量numberLength没有被声明为final,同时,你在PhoneNumber构造函数中添加如下语句:
PhoneNumber(String phoneNumber){
numberLength = 7;
String currentNumber = phoneNumber.replaceAll(regularExpression,"");
if(currentNumber.length()== numberLength){
formattedPhoneNumber = currentNumber;
}else{
formattedPhoneNumber = null;
}
}
因为添加的这个语句,变量numberLength不在是有效的final。结果,Java编译器报一个错误“从一个内部类引用的局部变量必须为final或者有效的final”:
if(currentNumber.length()==numberLength)
从Java8开始,如果你在一个方法中声明一个局部类,它可以方法这个方法的参数。例如,
public void printOriginalNumbers() {
System.out.println("Original numbers are " + phoneNumber1 +
" and " + phoneNumber2);
}
方法printOriginalNumbers访问了参数PhoneNumber1和phoneNumber2。
局部类和内部类是相似的
局部类和内部类是相似的,因为他们不能定义或者声明任何的静态成员。静态方法中的局部类,如类PhoneNumber,被定义在静态方法validatePhoneNumber中,仅能够访问静态成员变量。例如,如果你没有将成员变量regularExpression定义为静态的,那么Java编译器将会报错“非静态变量不能被一个静态上下文访问”。
局部类为非静态,因为它们可以访问静态成员。因此,它们不能包含静态声明。
不能在一个块中声明一个接口;因为接口时静态继承的。比如,下面的代码不能正常编译,因为接口HelloThere在方法greetInEnglish中被定义:
public void greenInEnglish(){
interface HelloThere{
public void greet();
}
class EnglishHelloThere implements HelloThere{
public void greet(){
System.out.println("hello " +name);
}
}
HelloThere myGreeting = new EnglishHelloThere();
myGreeting.greet();
}
不能在局部类中声明静态块或者成员接口。