13

I have a misunderstanding about what an anonymous class in Java is. Consider the following simple example:

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

interface B{ int b = 1; }

DEMO

Why does the code compile? The JLS, chapt 15 says:

An anonymous class is always an inner class (§8.1.3); it is never static

But the JLS, chapt 8

An inner class is a nested class that is not explicitly or implicitly declared static.

So the anonymous class is an inner class. But we use them in the static context. Why is it correct here?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
St.Antario
  • 26,175
  • 41
  • 130
  • 318

3 Answers3

7

A class can be created in a static context without being declared static, and this is what is happening here. Let's look at what being declared static, and created in a static context means:

The difference between an anonymous class created in a static context and a non-static context is whether it has an enclosing instance:

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.

A nested class that is declared static allows static members:

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.

By saying a nested class that is 'implicity declared static', it refers to things like classes within interfaces:

A member class of an interface is implicitly static (§9.5) so is never considered to be an inner class.

Anonymous classes are not declared static (neither explicitly with a keyword, or implicitly such as being inside an interface), and so do not allow the declaration of static members. They can however be created within a static context, which means that they don't refer to an enclosing instance.

Because the anonymous classes are not declared static, both quotes in the question are consistent.

Community
  • 1
  • 1
fgb
  • 18,439
  • 2
  • 38
  • 52
3

You should differentiate between anonymous and inner classes

With this statement you create a class implementing the interface B. The class has no name so it's called an anonymous class. The javac compile will create a class file with following naming rule YourClass$1.class (where 1 is a sequential number, based on the number of anonymous classes in YourClass.

B b = new B(){ };

The class created by new B(){ } cannot be declared as static. ("An anonymous class is always an inner class (§8.1.3); it is never static").

A static nested class example

class YourClass {
    static class StaticNestedClass {
    }
}

A non-static nested class example

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

There are two types of nested classes: static and non-static. Nested classes which are declared static are so-called static nested classes, whereas nested classes not declared as static are so-called inner classes.

SubOptimal
  • 22,518
  • 3
  • 53
  • 69
1

B is an inner interface. As such B is implicitely static and you can reference B in a static context. (From JLS 8.5.1 : A member interface is implicitly static (§9.1.1).)

But the anonymous class created through B is not static, and if referenced from a non static context, you could get access to the outer object :

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
            }

        };

    }
}

In your example, you could think you created an static anonymous inner class, because you created it :

  • from a static nested interface
  • in a static context - so with no access to the outer object

But same declaration in a non static context proves that a static nested interface creates a non static anonymous class

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252