为什么静态上下文中的匿名 class 有效
Why is an anonymous class in a static context valid
我对Java中的匿名class有什么误解。考虑以下简单示例:
public static void main (String[] args) throws java.lang.Exception
{
B b = new B(){ };
System.out.println(b.b);
}
interface B{ int b = 1; }
为什么代码可以编译? JLS, chapt 15 表示:
An anonymous class is always an inner class (§8.1.3); it is never
static
但是 JLS, chapt 8
An inner class is a nested class that is not explicitly or implicitly
declared static.
所以匿名 class 是一个内部 class。但是我们在静态上下文中使用它们。为什么这里是正确的?
你应该区分匿名和内部 classes
使用此语句创建一个实现接口 B 的 class。class 没有名称,因此称为匿名 class。 javac
编译将创建一个具有以下命名规则 YourClass$1.class 的 class 文件(其中 1 是序号,基于 YourClass 中匿名 class 的数量。
B b = new B(){ };
new B(){ }
创建的class不能声明为静态的。 ("An anonymous class is always an inner class (§8.1.3); it is never static").
静态嵌套 class 示例
class YourClass {
static class StaticNestedClass {
}
}
一个非静态嵌套 class 示例
class YourClass {
// An inner class is a nested class that is not explicitly or implicitly declared static.
class InnerClass {
}
}
有两种类型的嵌套 classes:静态和非静态。声明为静态的嵌套 class 就是所谓的 static nested classes
,而未声明为静态的嵌套 class 就是所谓的 inner classes
.
B 是一个内部 接口 。因此 B 是隐式静态的,您可以在静态上下文中引用 B。
(来自 JLS 8.5.1:成员接口是隐式静态的(§9.1.1)。)
但是通过 B 创建的匿名 class 不是静态的,如果从非静态上下文中引用,您可以访问外部对象:
public class Main{
public static void main(String[] args) throws java.lang.Exception {
B b = new B() {
@Override
public Ess3 getParent() {
//return Ess3.this; ERROR : non static variable cannot be referenced from static context
return null;
}
};
System.out.println(b.b);
}
interface B {
int b = 1;
Ess3 getParent();
}
/* a non static method */
void foo() {
B b = new B() {
@Override
public Ess3 getParent() {
return Ess3.this; // this anonymous class is not static
}
};
}
}
在您的示例中,您可能认为您创建了一个静态匿名内部 class,因为您创建了它 :
- 来自静态嵌套界面
- 在静态上下文中 - 因此无法访问外部对象
但非静态上下文中的相同声明证明静态嵌套接口创建非静态匿名 class
可以在静态上下文中创建一个 class 而无需声明为静态,这就是这里发生的情况。让我们看看声明为静态并在静态上下文中创建意味着什么:
在静态上下文中创建的匿名 class 与非静态上下文的区别在于它是否具有封闭实例:
If C is an anonymous class, then:
If the class instance creation expression occurs in a static context, then i has no immediately enclosing instance.
Otherwise, the immediately enclosing instance of i is this.
声明为静态的嵌套 class 允许静态成员:
An inner class is a nested class that is not explicitly or implicitly declared static.
A nested class that is not an inner class may declare static members
freely, in accordance with the usual rules of the Java programming
language.
通过说嵌套的 class 即 'implicity declared static',它指的是接口中的 classes 之类的东西:
A member class of an interface is implicitly static (§9.5) so is never
considered to be an inner class.
匿名 classes 未声明为静态(既未使用关键字显式声明,也未隐式声明,例如在接口内),因此不允许声明静态成员。然而,它们可以在静态上下文中创建,这意味着它们不引用封闭实例。
因为匿名classes没有声明为static,所以问题中的两个引号是一致的。
我对Java中的匿名class有什么误解。考虑以下简单示例:
public static void main (String[] args) throws java.lang.Exception
{
B b = new B(){ };
System.out.println(b.b);
}
interface B{ int b = 1; }
为什么代码可以编译? JLS, chapt 15 表示:
An anonymous class is always an inner class (§8.1.3); it is never static
但是 JLS, chapt 8
An inner class is a nested class that is not explicitly or implicitly declared static.
所以匿名 class 是一个内部 class。但是我们在静态上下文中使用它们。为什么这里是正确的?
你应该区分匿名和内部 classes
使用此语句创建一个实现接口 B 的 class。class 没有名称,因此称为匿名 class。 javac
编译将创建一个具有以下命名规则 YourClass$1.class 的 class 文件(其中 1 是序号,基于 YourClass 中匿名 class 的数量。
B b = new B(){ };
new B(){ }
创建的class不能声明为静态的。 ("An anonymous class is always an inner class (§8.1.3); it is never static").
静态嵌套 class 示例
class YourClass {
static class StaticNestedClass {
}
}
一个非静态嵌套 class 示例
class YourClass {
// An inner class is a nested class that is not explicitly or implicitly declared static.
class InnerClass {
}
}
有两种类型的嵌套 classes:静态和非静态。声明为静态的嵌套 class 就是所谓的 static nested classes
,而未声明为静态的嵌套 class 就是所谓的 inner classes
.
B 是一个内部 接口 。因此 B 是隐式静态的,您可以在静态上下文中引用 B。 (来自 JLS 8.5.1:成员接口是隐式静态的(§9.1.1)。)
但是通过 B 创建的匿名 class 不是静态的,如果从非静态上下文中引用,您可以访问外部对象:
public class Main{
public static void main(String[] args) throws java.lang.Exception {
B b = new B() {
@Override
public Ess3 getParent() {
//return Ess3.this; ERROR : non static variable cannot be referenced from static context
return null;
}
};
System.out.println(b.b);
}
interface B {
int b = 1;
Ess3 getParent();
}
/* a non static method */
void foo() {
B b = new B() {
@Override
public Ess3 getParent() {
return Ess3.this; // this anonymous class is not static
}
};
}
}
在您的示例中,您可能认为您创建了一个静态匿名内部 class,因为您创建了它 :
- 来自静态嵌套界面
- 在静态上下文中 - 因此无法访问外部对象
但非静态上下文中的相同声明证明静态嵌套接口创建非静态匿名 class
可以在静态上下文中创建一个 class 而无需声明为静态,这就是这里发生的情况。让我们看看声明为静态并在静态上下文中创建意味着什么:
在静态上下文中创建的匿名 class 与非静态上下文的区别在于它是否具有封闭实例:
If C is an anonymous class, then:
If the class instance creation expression occurs in a static context, then i has no immediately enclosing instance.
Otherwise, the immediately enclosing instance of i is this.
声明为静态的嵌套 class 允许静态成员:
An inner class is a nested class that is not explicitly or implicitly declared static.
A nested class that is not an inner class may declare static members freely, in accordance with the usual rules of the Java programming language.
通过说嵌套的 class 即 'implicity declared static',它指的是接口中的 classes 之类的东西:
A member class of an interface is implicitly static (§9.5) so is never considered to be an inner class.
匿名 classes 未声明为静态(既未使用关键字显式声明,也未隐式声明,例如在接口内),因此不允许声明静态成员。然而,它们可以在静态上下文中创建,这意味着它们不引用封闭实例。
因为匿名classes没有声明为static,所以问题中的两个引号是一致的。