当前位置: 首页 > 知识库问答 >
问题:

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

赵晟睿
2023-03-14

我对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; }

演示

代码为什么编译?JLS,第15章说:

匿名类总是一个内部类(§8.1.3);它从来不是静态的

但是JLS,第8章

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

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

共有3个答案

呼延德华
2023-03-14

B是一个内部接口。因此,B是隐式静态的,您可以在静态上下文中引用B。(来自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
            }

        };

    }
}

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

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

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

陆宇航
2023-03-14

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

使用此语句,您创建了一个实现接口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 {
    }
}

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

柳深
2023-03-14

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

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

如果C是一个匿名类,那么:

>

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

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

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

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

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

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

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

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

 类似资料:
  • 问题内容: 我对Java中的匿名类有什么误解。考虑以下简单示例: 演示 为什么要编译代码?在JLS,CHAPT 15 说: 匿名类始终是内部类(第8.1.3节);它永远不会是静态的 但是JLS,第8章 内部类是未显式或隐式声明为static的嵌套类。 因此,匿名类是内部类。但是我们在静态上下文中使用它们。为什么这里正确? 问题答案: 可以在静态上下文中创建类而无需将其声明为静态,这就是在这里发生的

  • 问题内容: 我在构建ORM库时要考虑到重用和简单性。一切都进行得很好,除了我被愚蠢的继承限制所困。请考虑以下代码: 显然,这不是我所期望的行为(尽管实际行为也很有意义)。因此,我的问题是,你们是否知道在父类中获得子类名称的意思。 问题答案: 简而言之。这不可能。在php4中,您可以实施可怕的破解(检查),但是该方法在PHP5中不起作用。参考资料: 37684 34421 编辑 :PHP 5.3中后

  • 我真的对此感到困惑!我有2个班,俱乐部和会员。在Membership中,我有方法getMonth();在Club中,我有joinedMonth(),它接受参数'month'--所以用户输入一个月,然后我希望它返回在该特定月份加入的成员资格。 我试图从Club类调用getMonth()方法,这样我就可以继续比较月份的整数。但是,当我试图调用该方法时,我只得到提到的“非静态方法getMonth()不能

  • 问题内容: 根据JLS: 15.9.5匿名类声明编译器会自动从类实例创建表达式派生匿名类声明。 匿名类从不抽象(第8.1.1.1节)。匿名类始终是内部类(第8.1.3节);它永远不是静态的(第8.1.1节,第8.5.2节)。 匿名类始终是隐式最终的(第8.1.1.2节) 。 这似乎是一个特定的设计决定,所以它有一定的历史。 如果我选择上这样的课: 如果选择的话,为什么不允许我再次对其进行子类化?

  • 我在旧的遗留系统中找到了这段代码,如果没有任何问题,我不想去碰它。 但是我觉得这段代码有一些缺陷,我找不到它。这是不是常见的模式,还是有一些隐藏的陷阱或内存泄漏? 此代码用于片段 更新:我怀疑匿名内部类的对象引用了父片段,由于该类的对象保存在静态字段中,因此永远不会收集,因此也永远不会收集父片段。我的推理错了吗?

  • 我得到两个错误: Java:不兼容类型:无法推断类型变量R(参数不匹配;方法引用无效) 对toString的引用是不明确的,java.lang.Integer中的方法toString(int)和java.lang.Integer中的方法toString()都是不明确的 并且编译器无法推断所需的方法引用。 但是关于第二个,编译器引用的静态上下文在哪里? 这个错误与Integer类的方法toStrin