The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
Local classes are classes that are defined in a block, which is a group of zero or more statements between balanced braces.局部类是在块中定义的类,块是平衡大括号之间的一组零或多个语句。You typically find local classes defined in the body of a method.通常可以在方法体中找到定义的局部类。
This section covers the following topics:本节涵盖以下主题:
You can define a local class inside any block (see Expressions, Statements, and Blocks for more information).可以在任何块内定义局部类(有关详细信息,请参阅表达式、语句和块)。For example, you can define a local class in a method body, a 例如,可以在方法体、for
loop, or an if
clause.for
循环或if
子句中定义局部类。
The following example, 下面的示例LocalClassExample
, validates two phone numbers.LocalClassExample
验证两个电话号码。It defines the local class 它在PhoneNumber
in the method validatePhoneNumber
: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"); } }
The example validates a phone number by first removing all characters from the phone number except the digits 0 through 9.该示例通过首先删除电话号码中除数字0到9之外的所有字符来验证电话号码。After, it checks whether the phone number contains exactly ten digits (the length of a phone number in North America).之后,它会检查电话号码是否正好包含十位数字(北美电话号码的长度)。This example prints the following:此示例打印以下内容:
First number is 1234567890 Second number is invalid
A local class has access to the members of its enclosing class.局部类可以访问其封闭类的成员。In the previous example, the 在上一个示例中,PhoneNumber
constructor accesses the member LocalClassExample.regularExpression
.PhoneNumber
构造函数访问成员LocalClassExample.regularExpression
。
In addition, a local class has access to local variables.此外,局部类可以访问局部变量。However, a local class can only access local variables that are declared final.但是,局部类只能访问声明为final
的局部变量。When a local class accesses a local variable or parameter of the enclosing block, it captures that variable or parameter.当局部类访问封闭块的局部变量或参数时,它将捕获该变量或参数。For example, the 例如,PhoneNumber
constructor can access the local variable numberLength
because it is declared final; numberLength
is a captured variable.PhoneNumber
构造函数可以访问局部变量numberLength
,因为它被声明为final
;numberLength
是一个捕获的变量。
However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final.然而,从JavaSE8开始,局部类可以访问封闭块的最终或有效最终的局部变量和参数。A variable or parameter whose value is never changed after it is initialized is effectively final.一个变量或参数的值在初始化后永远不会改变,它实际上是最终的。For example, suppose that the variable 例如,假设变量numberLength
is not declared final, and you add the highlighted assignment statement in the PhoneNumber
constructor to change the length of a valid phone number to 7 digits:numberLength
未声明为final
,并在PhoneNumber
构造函数中添加突出显示的赋值语句,以将有效电话号码的长度更改为7位:
PhoneNumber(String phoneNumber) { numberLength = 7; String currentNumber = phoneNumber.replaceAll( regularExpression, ""); if (currentNumber.length() == numberLength) formattedPhoneNumber = currentNumber; else formattedPhoneNumber = null; }
Because of this assignment statement, the variable 由于这个赋值语句,变量numberLength
is not effectively final anymore.numberLength
不再是有效的最终。As a result, the Java compiler generates an error message similar to "local variables referenced from an inner class must be final or effectively final" where the inner class 因此,Java编译器会生成类似于“从内部类引用的局部变量必须是最终或有效最终”的错误消息,其中内部类PhoneNumber
tries to access the numberLength
variable:PhoneNumber
尝试访问numberLength
变量:
if (currentNumber.length() == numberLength)
Starting in Java SE 8, if you declare the local class in a method, it can access the method's parameters.从Java SE 8开始,如果在方法中声明局部类,它可以访问该方法的参数。For example, you can define the following method in the 例如,您可以在PhoneNumber
local class:PhoneNumber
局部类中定义以下方法:
public void printOriginalNumbers() { System.out.println("Original numbers are " + phoneNumber1 + " and " + phoneNumber2); }
The method printOriginalNumbers
accesses the parameters phoneNumber1
and phoneNumber2
of the method validatePhoneNumber
.printOriginalNumbers
方法访问validatePhoneNumber
方法的参数phoneNumber1
和phoneNumber2
。
Declarations of a type (such as a variable) in a local class shadow declarations in the enclosing scope that have the same name.局部类中的类型声明(如变量)会在封闭范围中隐藏具有相同名称的声明。See Shadowing for more information.有关详细信息,请参阅阴影。
Local classes are similar to inner classes because they cannot define or declare any static members.局部类与内部类类似,因为它们不能定义或声明任何静态成员。Local classes in static methods, such as the class 静态方法中的局部类,例如在静态方法PhoneNumber
, which is defined in the static method validatePhoneNumber
, can only refer to static members of the enclosing class.validatePhoneNumber
中定义的类PhoneNumber
,只能引用封闭类的静态成员。For example, if you do not define the member variable 例如,如果未将成员变量regularExpression
as static, then the Java compiler generates an error similar to "non-static variable regularExpression
cannot be referenced from a static context."regularpression
定义为静态,则Java编译器将生成类似于“无法从静态上下文引用非静态变量regularExpression
”的错误。
Local classes are non-static because they have access to instance members of the enclosing block.局部类是非静态的,因为它们可以访问封闭块的实例成员。Consequently, they cannot contain most kinds of static declarations.因此,它们不能包含大多数类型的静态声明。
You cannot declare an interface inside a block; interfaces are inherently static.不能在块内声明接口;接口本质上是静态的。For example, the following code excerpt does not compile because the interface 例如,由于接口HelloThere
is defined inside the body of the method greetInEnglish
: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(); }
You cannot declare static initializers or member interfaces in a local class.不能在局部类中声明静态初始值设定项或成员接口。The following code excerpt does not compile because the method 以下代码摘录未编译,因为方法EnglishGoodbye.sayGoodbye
is declared static
.EnglishGoodbye.sayGoodbye
声明为静态。The compiler generates an error similar to "modifier 'static' is only allowed in constant variable declaration" when it encounters this method definition:当编译器遇到此方法定义时,会生成类似于“修饰符'static'仅允许在常量变量声明中使用”的错误:
public void sayGoodbyeInEnglish() { class EnglishGoodbye { public static void sayGoodbye() { System.out.println("Bye bye"); } } EnglishGoodbye.sayGoodbye(); }
A local class can have static members provided that they are constant variables.局部类可以有静态成员,只要它们是常量变量。(A constant variable is a variable of primitive type or type (常量变量是基元类型或String
that is declared final and initialized with a compile-time constant expression.String
类型的变量,它被声明为final
并用编译时常量表达式初始化。A compile-time constant expression is typically a string or an arithmetic expression that can be evaluated at compile time.编译时常量表达式通常是可以在编译时计算的字符串或算术表达式。See Understanding Class Members for more information.)有关详细信息,请参阅了解类成员。)The following code excerpt compiles because the static member 编译以下代码摘录是因为静态成员EnglishGoodbye.farewell
is a constant variable: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(); }