14
March
2006

Анонимные классы в Java (anonymous inner classes)

Posted in: Java technologies, J2SE |

English version of this article you can find here.
Практически во всех статьях об inner классах допущен ряд о?ибок по поводу анонимных классов:

  • они не имеют имени;
  • они не могут быть объявлены статическими;
  • они могут быть созданы только один раз при декларировании.

Это все неправда!
Допустим у нас есть следующий код:

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

?мя анонимного класса можно получить так:

anonym.getClass().toString().

Скорее всего вы получите что-то вроде этого: Anonymous$1.
Анонимный класс может быть как статическим, так и нестатическим. Это напрямую зависит от того, статическим или нестатическим является блок, в котором анонимный класс был объявлен. В примере, который указан вы?е, анонимный класс будет статическим. В этом случае можно создать еще один экземпляр класса таким способом:

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

В версии JDK 1.5 приведение типа (по-русски type cast :)) делать не нужно.
Если же анонимный класс был объявлен внутри нестатического блока, то для создания второго экземпляра анонимного класса нужно передать в его конструктор ссылку на обрамляющий класс. В противном случае получим InstantiationException.
Вот неболь?ой пример. Для его упрощения, я не использовал алгоритм поиска необходимого конструктора и списка его формальных параметров, а также опустил обработку Exception.

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();
  }
}

?нтересующий нас конструктор имеет модификатор видимости protected. Функция getConstructors(), в отличии от getDeclaredConstructors(), вернет список только public конструкторов.
Надеюсь, статья была вам интересна. В любом случае, комментарии приветствуются.

Еще про внутренние классы в Java можно прочитать здесь - Внтуренние классы в Java.

Updated (26.08.2009):
“За все, что Вы когда-либо писали, Вам придется отвечать всю остав?уюся жизнь…” (c) Костя Чапюк, то есть я

Время идет, многие статьи на блоге уже постарели и поседели… Тем не менее до сих пор находятся люди, которые не смотрят на дату публикации статей и почему-то хотят задеть меня или унизить мои “многолетназад?ние” порывы вести свой блог и делиться с миром моими наблюдениями.

Например, комментарий от bsv:

пожалуйста получи имя этого анонимного класса .)
new Thread(new Runnable() {
    public void run() {
        …
    }
}).start();
твой пример по этому поводу, извени, слегка притянут за у?и .)

Хотел сначала проигнорировать, но может кому-то интересно будет. Позволю себе немного упростить задание, а то с тремя точками плохо компилится…

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. ?ндекс “1″ за у?и не притянут… Можно было выкинуть из массива currentThread; остав?ийся Thread - на? клиент.

8 Comments »

RSS feed for comments on this post. TrackBack URI



pilgrim
June 22, 2006 #

Отличная статья!
P.S. “Пе?и исчо”

ааа
October 18, 2006 #

статья хоро?ая. короткая. понятная. простая. без ли?них загогулин. хоро?о что есть люди которые такую инфу выве?ивают. вообще классные наблюдения :)

Twister
November 10, 2006 #

Дзенкую барзо!

Отличный сайт :)

bsv
August 13, 2009 #

пожалуйста получи имя этого анонимного класса .)

new Thread(new Runnable() {
public void run() {

}
}).start();

твой пример по этому поводу, извени, слегка притянут за у?и .)

August 26, 2009 #

2 bsv: дополнил статью

September 26, 2009 #

[…] другим углом обзора. Поясню луч?е на примере. В статье Анонимные классы в Java (anonymous inner classes) автор опровергает такие утверждения об анонимных […]

Paul
October 26, 2009 #

Малацца! Так держать!

Anton Krupnov
January 13, 2010 #

Очень хоро?ая статья, при внимательном чтении помогает понять механизм обработки анонимных классов, на мой взгляд это гораздо более глубокий уровень понимания.
Спасибо боль?ое за такую информацию! :)

Leave a comment

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong> <pre>