2012-03-23 2 views
0

Являются ли анонимные внутренние классы частными по умолчанию? Могу ли я сделать их общедоступными?общедоступный анонимный внутренний класс в Java

Мне нужно получить доступ к методам отражения.

+1

Если это анонимный внутренний класс, как компилятор знал бы, где искать эти методы? Почему вы не просто создаете публичный класс и используете его в тех местах, где вам нужно, а не для использования анонимного класса? – jzworkman

ответ

2

Вы можете использовать методы анонимного внутреннего класса с отражением. См. getDeclaredMethods(). Не забудьте позвонить в setAccessible(true) на номер Method, чтобы избежать IllegalAccessException.

Object testObject = new Object() { 
    private void testMe() { 
     System.out.println("testme"); 
    } 
}; 
Method m = testObject.getClass().getDeclaredMethod("testMe"); 
m.setAccessible(true); 
m.invoke(testObject); // prints out "testme" 

заметить также, что если есть SecurityManager это не будет возможным, см What is the security risk of object reflection?

Предупреждения: Примите во внимание, что анонимные внутренние классы являются своим родом одноразовых определений класса. После использования вам больше никогда не понадобится их в другом месте. Точно так же, как @ PéterTörök сказал, трудно сказать без лишнего контекста вашей проблемы, но, если у вас есть контроль над этим классом, вероятно, было бы лучше деанонизировать этот класс (создание частного внутреннего класса или даже публичного) и разоблачить этот метод для классов, которые в нем нуждаются.

7

Анонимные внутренние классы анонимны по причине: они не предназначены для доступа непосредственно из внешнего мира, только через ссылочный параметр variable/method. (И по той же причине, что они являются частными тоже.)

Я думаю, вы могут попытаться получить доступ к такому классу с помощью отражения, используя его компилятор генерируется имя (например, OuterClass$1), однако это зависит от конкретной реализации и может изменяться когда вы добавите другой анонимный внутренний класс в тот же внешний класс или в следующую версию JVM. Поэтому такое решение было бы очень хрупким.

Почему вы на самом деле хотите это сделать? Если вы объясните свою фактическую проблему, мы сможем предложить лучшую альтернативу.

+0

Я не согласен. Единственная разница между не анонимными и анонимными внутренними классами заключается в том, что у последних нет имени. Причиной этого является краткость, а не безопасность. Поэтому причина анонимных классов не может быть общедоступной, так как синтаксис не был предложен. ИМХО. – Dims

+0

+1 Не нужно использовать имя класса, сгенерированное компилятором, если у вас есть экземпляр (хотя это присуще анонимному внутреннему классу). –

+0

@ XaviLópez, действительно. Если у вас есть экземпляр, зачем вам размышлять? –

1

Анонимные внутренние классы по умолчанию являются закрытыми. Для использования с рефлексами вы можете посмотреть здесь - Java reflection: How can I retrieve anonymous inner classes?

+1

У анонимных внутренних классов есть доступ по умолчанию (закрытый пакет), а не частный. –

+0

моя ошибка спасибо за исправление – aretai

1

Анонимные внутренние классы имеют доступ к частному (по умолчанию). В Java 6 они являются окончательными, если объявлены в статическом контексте, но не окончательны в других контекстах. (Я считаю, но не проверял, что это изменилось в Java 7, так что они всегда окончательным; см Section 15.9.5 of the Java Language Specification.)

Например, этот класс имеет четыре анонимных внутренних классов:

public class InnerTest { 
    public Runnable foo1 = new Runnable() { 
     public void run() {foo1();} 
     void foo1() {} 
    }; 
    private Runnable foo2 = new Runnable() { 
     public void run() {foo2();} 
     void foo2() {} 
    }; 
    public static Runnable foo3 = new Runnable() { 
     public void run() {foo3();} 
     void foo3() {} 
    }; 
    private static Runnable foo4 = new Runnable() { 
     public void run() {foo4();} 
     void foo4() {} 
    }; 
} 

Когда скомпилированный с javac (версия 1.6.0_26), он генерирует четыре анонимных внутренних класса.Декомпиляция с javap -c показывает:

  • InnerTest$1 (foo1) — пакет частных
  • InnerTest$2 (foo2) — пакет частных
  • InnerTest$3 (foo3) — пакет приватным и окончательный
  • InnerTest$4 (foo4) — пакета приватное и окончательный

Обратите внимание, что доступ к переменному, к которой анонимный экземпляру внутреннего класса быть назначен не имеет значения.