资讯专栏INFORMATION COLUMN

Java™ 教程(局部类)

meislzhua / 411人阅读

局部类

局部类是在块中定义的类,它是一对大括号之间的一组零个或多个语句,你通常会在方法体中找到定义的局部类。

声明局部类

你可以在任何块中定义局部类(有关详细信息,请参阅表达式、语句和块),例如,你可以在方法体、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,因为它被声明为finalnumberLength是捕获的变量。

但是,从Java SE 8开始,局部类可以访问final或有效final的封闭块的局部变量和参数,在初始化之后其值永远不会改变的变量或参数实际上是final,例如,假设变量numberLength未声明为final,并且你在PhoneNumber构造函数中添加赋值语句,以将有效电话号码的长度更改为7位数:

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方法的参数phoneNumber1phoneNumber2

遮蔽和局部类

在具有相同名称的封闭范围内的局部类遮蔽声明中类型的声明(例如变量),有关更多信息,请参阅遮蔽。

局部类与内部类相似

局部类与内部类类似,因为它们无法定义或声明任何静态成员,静态方法中的局部类,例如在静态方法validatePhoneNumber中定义的类PhoneNumber,只能引用封闭类的静态成员。例如,如果未将成员变量regularExpression定义为static,则Java编译器会生成类似于“非静态变量regularExpression无法从静态上下文引用”的错误。

局部类是非静态的,因为它们可以访问封闭块的实例成员,因此,它们不能包含大多数类型的静态声明。

你不能在一个块内声明一个接口;接口本质上是静态的,例如,以下代码片段不会编译,因为接口HelloThere是在方法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被声明为static,当遇到此方法定义时,编译器会生成类似于“修饰符"static"的错误,只允许在常量变量声明中使用”:

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

局部类可以具有静态成员,前提是它们是常量变量(常量变量是原始类型或类型String的变量,它被声明为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();
    }
上一篇:嵌套类 下一篇:匿名类

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72336.html

相关文章

  • Java教程(匿名

    匿名类 匿名类可以使你代码更简洁,它们使你能够同时声明和实例化一个类,它们就像局部类,除了它们没有名称,如果你只需要使用局部类一次,请使用它们。 声明匿名类 虽然局部类是类声明,但匿名类是表达式,这意味着你在另一个表达式中定义该类,以下示例HelloWorldAnonymousClasses在局部变量frenchGreeting和spanishGreeting的初始化语句中使用匿名类,但使用局部类...

    xietao3 评论0 收藏0
  • 阿里 Java 手册系列教程:为啥强制子、父变量名不同?

    摘要:所以看出和两个的对应指针数一样,一个为一个为这就引出了变量的知识点,如手工画的图二为啥强制子类父类变量名不同阿里巴巴手册是这样写的强制避免在子父类的成员变量之间或者不同代码块的局部变量之间采用完全相同的命名方式,那会导致代码可读性降低。 摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 父子...

    XGBCCC 评论0 收藏0
  • Java教程(变量)

    变量 正如你在上一课中所了解到的,对象将其状态存储在字段中。 int cadence = 0; int speed = 0; int gear = 1; 什么是对象?讨论向你介绍了字段,但你可能还有一些问题,例如:命名字段的规则和约定是什么?除了int之外,还有哪些其他数据类型?在声明字段时是否必须初始化字段?如果未明确初始化字段,是否为字段分配了默认值?我们将在本课中探讨这些问题的答案,但在我们...

    elina 评论0 收藏0
  • Java教程(嵌套

    嵌套类 Java编程语言允许你在另一个类中定义类,这样的类称为嵌套类,如下所示: class OuterClass { ... class NestedClass { ... } } 术语:嵌套类分为两类:静态和非静态,声明为static的嵌套类称为静态嵌套类,非静态嵌套类称为内部类。 class OuterClass { ... stati...

    Cheng_Gang 评论0 收藏0
  • Java 10 实战第 1 篇:局部变量型推断

    摘要:就等于局部变量类型推断使用示例既然叫局部变量类型推断,以只能用在局部变量中,下面给出更多使用示例。,本次局部变量类型推断实战文章就到这里了,后续带来更多的的实战方面的文章。 现在 Java 9 被遗弃了直接升级到了 Java 10,之前也发过 Java 10 新特性的文章,现在是开始实战 Java 10 的时候了。 今天要实战的是 Java 10 中最重要的特性:局部变量类型推断,大家...

    HollisChuang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<