javaSE_8系列博客——Java语言的特性(三)--类和对象(17)--嵌套类(本地/局部类)

本地(局部)类是在块中定义的类,它是花括号之间的一组零个或多个语句。你通常会发现方法体中定义的局部类。

声明一个局部类

您可以在任何块中定义一个局部类(有关详细信息,请参阅表达式,语句和块)。例如,您可以在方法体,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;

        // Valid in JDK 8 and later:

        // int numberLength = 10;

        class PhoneNumber {

            String formattedPhoneNumber = null;

            PhoneNumber(String phoneNumber){
                // numberLength = 7;
                String currentNumber = phoneNumber.replaceAll(
                  regularExpression, "");
                if (currentNumber.length() == numberLength)
                    formattedPhoneNumber = currentNumber;
                else
                    formattedPhoneNumber = null;
            }

            public String getNumber() {
                return formattedPhoneNumber;
            }

            // Valid in JDK 8 and later:

//            public void printOriginalNumbers() {
//                System.out.println("Original numbers are " + phoneNumber1 +
//                    " and " + phoneNumber2);
//            }
        }

        PhoneNumber myNumber1 = new PhoneNumber(phoneNumber1);
        PhoneNumber myNumber2 = new PhoneNumber(phoneNumber2);

        // Valid in JDK 8 and later:

//        myNumber1.printOriginalNumbers();

        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");
    }
}

该示例通过首先从电话号码除去数字0到9之外的所有字符来验证电话号码。之后,它检查电话号码是否包含正好十位数字(北美电话号码的长度)。此示例打印以下内容:

First number is 1234567890
Second number is invalid

访问封闭类中的成员

局部类可以访问其封闭类的成员。在前面的例子中,PhoneNumber构造函数访问成员LocalClassExample.regularExpression。 另外,局部类可以访问局部变量。但是,局部类只能访问被声明为final的局部变量。当局部类访问包围块的局部变量或参数时,它会捕获该变量或参数。例如,PhoneNumber构造函数可以访问局部变量numberLength,因为它被声明为final; numberLength是一个捕获的变量。 然而,从Java SE 8开始,局部类可以访问最终或有效最终的封闭块的局部变量和参数。其值在初始化后永远不会更改的变量或参数是最终的。例如,假设变量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”的错误消息,内部类PhoneNumber将尝试访问numberLength变量:

if (currentNumber.length() == numberLength)

从Java SE 8开始,如果您在方法中声明局部类,则可以访问该方法的参数。例如,您可以在PhoneNumber局部类中定义以下方法:

public void printOriginalNumbers() {
    System.out.println("Original numbers are " + phoneNumber1 +
        " and " + phoneNumber2);
}

局部类的printOriginalNumbers方法访问封闭类中方法validatePhoneNumber的参数phoneNumber1和phoneNumber2。

局部类和内部类的关系

局部类与内部类类似,因为它们不能定义或声明任何静态成员。静态方法中的局部类(如静态方法validatePhoneNumber中定义的PhoneNumber类)只能引用封闭类的静态成员。

例如,如果没有将成员变量regularExpression定义为static,则Java编译器会生成类似于“静态上下文不能引用非静态变量regularExpression”的错误。局部类是非静态的,因为它们可以访问封闭块的实例成员。因此,它们不能包含大多数种类的静态声明。

您不能在块内声明一个接口 ; 接口本质上是静态的。例如,以下代码片段不编译,因为接口HelloThere是在方法body中定义的内容greetInEnglish:

 public void greetInEnglish() {
        interface HelloThere {
           public void greet();
        }
        class EnglishHelloThere implements HelloThere {
            public void greet() {
                System.out.println("Hello " + name);
            }
        }
        HelloThere myGreeting = new EnglishHelloThere();
        myGreeting.greet();
    }

您不能在局部类中声明静态初始化程序或成员接口。以下代码片段不编译,因为方法EnglishGoodbye.sayGoodbye被声明为静态的。编译器生成类似于“modifier ”的错误,当遇到此方法定义时,静态“仅允许在常量变量声明中”:

public void sayGoodbyeInEnglish() {
        class EnglishGoodbye {
            public static void sayGoodbye() {
                System.out.println("Bye bye");
            }
        }
        EnglishGoodbye.sayGoodbye();
    }

局部类可以具有静态成员,只要它们是常量变量。 (一个常量变量是一个原始类型或类型的字符串,它被声明为final,并使用编译时常量表达式初始化。编译时常量表达式通常是一个字符串或算术表达式,可以在编译时进行评估计算。)以下代码片段可以正常编译,因为静态成员EnglishGoodbye.farewell是一个常量变量:

public void sayGoodbyeInEnglish() {
        class EnglishGoodbye {
            public static final String farewell = "Bye bye";
            public void sayGoodbye() {
                System.out.println(farewell);
            }
        }
        EnglishGoodbye myEnglishGoodbye = new EnglishGoodbye();
        myEnglishGoodbye.sayGoodbye();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值