Java™ 教程(局部類)

局部類

局部類是在塊中定義的類,它是一對大括號之間的一組零個或多個語句,你一般會在方法體中找到定義的局部類。segmentfault

聲明局部類

你能夠在任何塊中定義局部類(有關詳細信息,請參閱表達式、語句和塊),例如,你能夠在方法體、for循環或if子句中定義局部類。函數

如下示例LocalClassExample驗證兩個電話號碼,它在validatePhoneNumber方法中定義了局部類PhoneNumbercode

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以外的全部字符來驗證電話號碼,以後,它會檢查電話號碼是否包含十位數字(北美電話號碼的長度),此示例打印如下內容:orm

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位數:get

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局部類中定義如下方法:io

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

上一篇:嵌套類

下一篇:匿名類

相關文章
相關標籤/搜索