Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么静态上下文中的匿名类有效_Java_Anonymous Class - Fatal编程技术网

Java 为什么静态上下文中的匿名类有效

Java 为什么静态上下文中的匿名类有效,java,anonymous-class,Java,Anonymous Class,我对Java中的匿名类有一个误解。考虑下面的简单例子: public static void main (String[] args) throws java.lang.Exception { B b = new B(){ }; System.out.println(b.b); } interface B{ int b = 1; } 为什么代码要编译?报告说: 匿名类始终是内部类(§8.1.3);从来都不是 静止的 但是 内部类是不是显式或隐式的嵌套类 声明为静态 所以匿名

我对Java中的匿名类有一个误解。考虑下面的简单例子:

public static void main (String[] args) throws java.lang.Exception
{
    B b = new B(){ };
    System.out.println(b.b);
}

interface B{ int b = 1; }

为什么代码要编译?报告说:

匿名类始终是内部类(§8.1.3);从来都不是 静止的

但是

内部类是不是显式或隐式的嵌套类 声明为静态


所以匿名类是一个内部类。但是我们在静态上下文中使用它们。这里为什么正确?

您应该区分匿名类和内部类

通过此语句,您创建了一个实现接口B的类。该类没有名称,因此称为匿名类。
javac
编译将使用以下命名规则创建一个类文件YourClass$1.class(其中1是一个序列号,基于YourClass中匿名类的数量)

B b = new B(){ };
new B(){}
创建的类不能声明为静态的。(“匿名类始终是内部类(§8.1.3);它从来不是静态的”)

静态嵌套类示例

class YourClass {
    static class StaticNestedClass {
    }
}
class YourClass {
    // An inner class is a nested class that is not explicitly or implicitly declared static.
    class InnerClass {
    }
}
非静态嵌套类示例

class YourClass {
    static class StaticNestedClass {
    }
}
class YourClass {
    // An inner class is a nested class that is not explicitly or implicitly declared static.
    class InnerClass {
    }
}

嵌套类有两种类型:静态和非静态。声明为静态的嵌套类称为
静态嵌套类
,而未声明为静态的嵌套类称为
内部类

B是内部接口。因此,B是隐式静态的,您可以引用B in静态上下文。 (来自JLS 8.5.1:成员接口是隐式静态的(§9.1.1)。)

但通过B创建的匿名类不是静态的,如果从非静态上下文引用,则可以访问外部对象:

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
            }

        };

    }
}
在您的示例中,您可能认为您创建了一个静态匿名内部类,因为您创建了它:

  • 从静态嵌套接口
  • 在静态上下文中-因此无法访问外部对象

但非静态上下文中的同一声明证明了静态嵌套接口创建了一个非静态匿名类

一个类可以在静态上下文中创建,而不被声明为静态,这就是这里发生的事情。让我们看看在静态上下文中声明为静态和创建为静态意味着什么:

在静态上下文和非静态上下文中创建的匿名类之间的区别在于它是否具有封闭实例:

如果C是匿名类,则:

  • 如果类实例创建表达式发生在静态上下文中,那么我没有立即封闭的实例

  • 否则,立即封闭的i实例就是这个

声明为静态的嵌套类允许静态成员:

内部类是不是显式或隐式声明为静态的嵌套类

非内部类的嵌套类可以声明静态成员 自由地,按照Java编程的常规规则 语言

通过说一个嵌套类是“隐式声明静态的”,它指的是接口中的类:

接口的成员类是隐式静态的(§9.5),因此永远不会 被认为是一个内部阶级

匿名类不是声明为静态的(既不是显式地使用关键字,也不是隐式地(例如在接口中),因此不允许声明静态成员。但是,它们可以在静态上下文中创建,这意味着它们不引用封闭实例


因为匿名类不是静态的,所以问题中的两个引用都是一致的。

我们正在寻找引用JLS的答案,而不是从您的理解中寻找答案。这是对内部类的基本介绍,但根本没有解决这个问题。请引用JLS来加强您的说法。@nhahdh:我想OP已经引用了编辑了JLS的相关部分,但我在另一个答案中读到了它。后期编辑的
B=new B(){};
不是一个匿名类。它可以工作,因为它在静态上下文中使用,它将内部类本身声明为禁止的静态。@Shywim那么
new B(){}
创建的对象是什么类型的?