Javenue logo

Javenue

Программирование на Java

Информационные технологии

Anonymous inner classes in Java

[Версия статьи на русском языке доступна здесь.]

There are a lot of articles through Internet which have mistakes and myths regarding anonymous inner classes in Java. For example, anonymous inner class:

  • has no name;
  • can't be declared as static;
  • can be instantiated only once.

Let me show you the truth.

Consider the following code:

public class Anonymous {
    public static void main(String[] args) {
        Runnable anonym = new Runnable() {
            public void run() {
            }
        };
    }
}

In order to get the name of inner class write down the following:

anonym.getClass().toString().

You’ll get something like that: Anonymous$1.

Anonymous class can be either static or non-static. It depends on the block in which the class have been declared. In the previous example the anonymous class was static. In this case, we can create the second instance of this class in such a way:

Runnable anonym2 = (Runnable) anonym
    .getClass().newInstance().

There is no need in type cast in JDK 1.5.

If the anonymous class was declared in non-static block, we have to provide a reference to the outer class to the proper constructor (in reflection veritas!). In the other case we'll get the InstantiationException.

Here we have an example (determining of proper constructor and exception handling are not shown below):

public class Anonymous {
  public void nonStaticMethod() {
    Runnable anonym = new Runnable() {
      public void run() {
      }
    };
    Constructor[] constructors = anonym.getClass()
        .getDeclaredConstructors();
    Object[] params = new Object[1];
    params[0] = this;

    Runnable anonym2 = (Runnable) constructors[0]
        .newInstance(params);
  }

  public static void main(String[] args) {
    Anonymous example = new Anonymous();
    example.nonStaticMethod();
  }
}

In this example we have to use getDeclaredConstructors instead of getConstructors. Method getConstructors will return only public constructors, while needed constructor is protected one.

Updated (26.08.2009)

Some articles on the blog are already outdated and it is very hard to find time and keep them synced... Nevertheless, some visitors enforce me to do that.

For instance, bsv wrote:

please find the name of this class .)
new Thread(new Runnable() {
    public void run() {
        …
    }
}).start();
I'm sorry but your example is a bullshit .)

I wanted to ignore the comment firstly, but then decided to accept the challenge. Please, see the following code:

public class LookHereItIs {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            public void run() {
                while (true)
                    try { Thread.sleep(1000); }
                    catch (InterruptedException e) { }
            }
        }).start();

        ThreadGroup group = Thread.currentThread().getThreadGroup();
        Thread[] threads = new Thread[group.activeCount()];
        group.enumerate(threads);

        Field field;
        try { field = Thread.class.getDeclaredField("target"); }
        catch (NoSuchFieldException e) { throw new RuntimeException(e); }

        field.setAccessible(true);
        Runnable runnable;
        try { runnable = (Runnable) field.get(threads[1]); }
        catch (IllegalAccessException e) { throw new RuntimeException(e); }

        System.out.println(runnable.getClass().toString());
    }
}

P.S. I have simplified the code a little and used index 1... But you always can remove currentThread from the array. The other thread is what we were looking for. That's it.

I really do appreciate your comments on this article. Have a nice day.


Комментариев: 1

  Выйти

  * для публикации комментариев нужно  

Михайло Ведмідь:

Could you write what is the purpose of using Anonymous classes. And also can Anonymous classes be not only "inner"?