Are static anonymous classes specific errors in Java?

I read elsewhere that a static anonymous class does not make sense - all anonymous classes must be bound to an instance of the enclosing type. But the compiler will let you do this. Here is an example:

class Test { /* * What the difference at between * Test.likeThis and Test.likeThat? */ // This is obviously okay: private static final class LikeThat { @Override public String toString() { return "hello!"; } } public static Object likeThat = new LikeThat(); // What about this - is it really any different? public static Object likeThis = new Object() { @Override public String toString() { return "hello!"; } }; } 

What's going on here?

+4
source share
9 answers

I see nothing wrong with static anonymous classes

+7
source

From the Java Language Specification, Section 8.1.3 :

An instance of the inner class I , whose declaration takes place in a static context , does not have lexically-closing instances. However, if I am immediately declared in a static method or static initializer, then I have a closed block, which is the innermost block expression that lexically spans declaration I.

Your anonymous class (one likeThis is an instance) occurs in a static context, so it is not tied to an instance-instance. However, it seems that it can refer to the final variables of its enclosing block (see the rest of section 8.1.3, they give an example).

Btw, your wording is a little misleading, you are actually referring to a static instance of an anonymous class (this is an instance, static, not a class).

+7
source

As with any language, you should just think about why you are doing this. If you have many of these instances, I would question the design decisions, but this does not necessarily mean that the pattern should never be respected.

And, of course, always consider the testability of the class and can you provide a double test, if necessary

+5
source

I don’t think they have any meaning. If you do not need a reference to the surrounding object, then it is better to leave it static. Later it can easily develop in a separate class.

The widespread enum idiom (pre Java 5) used a similar approach with anonymous static descendants of the enum class. It is probably better now to stick with the Java 5 enum for this case.

If you can find an adequate real-world application for anonymous static classes - why not use them?

+1
source

I do this all the time. This is especially convenient for special implementations of utility program interfaces, for example:

 /** A holder for {@link Thing}s. */ public interface ThingsHolder { /** A {@link ThingsHolder} with nothing in it. */ public static final ThingsHolder EMPTY_HOLDER = new ThingsHolder() { @Override public Iterable<Thing> getThings() { return Collections.emptySet(); } }; /** Provides some things. */ Iterable<Thing> getThings(); } 

You can create a closed static inner class called EmptyHolder , and perhaps in some cases this will make the code more readable, but there is no reason why you should do this.

+1
source

According to this answer , which refers to JLS, anonymous classes are never static , but when created in a "static context" they do not have a "closing instance".

Nonetheless,

  • They give the same error at compile time if you try to reference Test.this (the non-static this variable cannot refer to a static context)
  • At run time, the only obvious difference between class objects (except for the name) is that Test$1 is an “anonymous class” and Test$LikeThat is a “member class”. Both of them have a class; none of them have a built-in constructor or method. (I only checked probable methods, there may be other differences).
    • EDIT: According to getModifiers() , Test $ 1 is static and Test$LikeThat is static final ! According to the language specification Test$1 should be final . Hm ...
  • According to javap -c -verbose -s -private -l ,

    • Test$1 indicates "EnclosingMethod" (perhaps Test static initializer?)
    • Test$LikeThat has an additional entry in the "InnerClass" section ( #12; //class Test$1 ) and the curious constructor Test$LikeThat(Test$1) . This is because LikeThat is private , which makes the constructor private , so the compiler generates a trampoline to be called from Test .

If you delete private , they seem to compile in much the same way, except for the EnclosingMethod entry.

Test$1 does not have a field final Test this$0; which would be if it were defined in a non-stationary context.

+1
source

It seems completely legal to me. Since the anonymous class is static , it will not refer to any encompassing class, but there should not be any evil consequences.

Well, besides being a hidden singleton object, it’s pretty evil.

0
source

Of course, this is not so. I always use static nested classes unless I need an implicit connection to the surrounding object.

In java terminology, a nested class: = a class declared in another class (or interface). Inner classes are those nested classes that have a linked instance from the surrounding class. (Non-static member classes, local classes, anonymous classes).

Implicit communication can sometimes prevent garbage collection.

0
source

This can be very convenient due to the ability to make circular links:

 class A { public static final A _1 = new A() { public A foo() { return _2; } }; public static final A _2 = new A() { public A foo() { return _1; } }; } 

Creating multiple objects containing links to each other can be very inconvenient without using anonymous classes.

-1
source

All Articles