Необоснованные анонимные классы в Java
Прошло около 6 лет с тех пор, как я написал Java, поэтому, пожалуйста, извините за ржавчину.
Я работаю с библиотечным методом, который требует, чтобы я передал его Class
объекты. Так как мне придется вызывать этот метод динамическое количество раз, каждый раз с немного другим Class
аргумент, я хотел передать это анонимный класс.
Тем не менее, вся документация / учебные пособия, которые я смог найти до сих пор, говорит только о создании экземпляров анонимных классов, например:
new className(optional argument list){classBody}
new interfaceName(){classBody}
Могу ли я определить анонимный класс без его создания? Или, может быть, более четко, я могу создать Class
объект для анонимного класса?
6 ответов
К сожалению, вы никак не можете избежать инстанцирования здесь. Вы можете сделать его неактивным, однако:
foo((new Object() { ... }).getClass());
Конечно, это не может быть вариантом, если вам нужно наследовать от некоторого класса, который выполняет некоторые действия в конструкторе.
РЕДАКТИРОВАТЬ
Ваш вопрос также говорит, что вы хотите позвонить foo
msgstr "каждый раз с немного другим аргументом класса". Вышесказанное не сделает этого, потому что все еще будет одно анонимное определение внутреннего класса, даже если вы поместите выражение new в цикл. Так что на самом деле он ничего не купит по сравнению с определением именованного класса. В частности, если вы пытаетесь сделать это для захвата значений некоторых локальных переменных, новый экземпляр вашего анонимного класса, который foo
создаст с помощью Class
переданный объект не захватит их.
короткий ответ
вы не можете (используя только классы JDK)
длинный ответ
попробуй:
public interface Constant {
int value();
}
public static Class<? extends Constant> classBuilder(final int value) {
return new Constant() {
@Override
public int value() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}.getClass();
}
давайте создадим два новых класса "параметрических" классов:
Class<? extends Constant> oneClass = createConstantClass(1);
Class<? extends Constant> twoClass = createConstantClass(2);
однако вы не можете создать экземпляр этого класса:
Constant one = oneClass.newInstance(); // <--- throws InstantiationException
Constant two = twoClass.newInstance(); // <--- ditto
он потерпит неудачу во время выполнения, поскольку существует только один экземпляр для каждого анонимного класса.
Однако вы можете создавать динамические классы во время выполнения, используя библиотеки манипулирования байт-кодом, такие как ASM. Другой подход заключается в использовании динамических прокси, но этот подход является недостатком, заключающимся в том, что вы можете использовать только методы интерфейса с прокси (поэтому вам нужен интерфейс Java).
Вы не можете получить доступ к объекту Class анонимного класса, не установив его. Однако, если вам нужен только доступ к классу, вы можете определить локальные классы в вашем методе и ссылаться на них, используя синтаксис литерала ClassName.class.
Вы можете ссылаться только на анонимный класс ОДИН РАЗ. Если вы не создадите его экземпляр там, вы не сможете создать его экземпляр, так как у вас нет имени для него.
Следовательно, я считаю, что анонимные классы могут использоваться только в сочетании с "новым BaseClass()".
В вашей ситуации вы передадите объект BaseClass своему методу, выполняющему работу, и создадите экземпляр анонимного объекта в исходном коде, когда вам понадобится передать объект.
Вы можете получить доступ к объекту класса анонимного класса, вызвав .getClass()
на это сразу после создания. Но что хорошего это будет делать?
Я думаю, что ключ в этой части того, что вы сказали:
Я работаю с библиотечным методом, который требует, чтобы я передал ему объекты класса.
Почему он хочет, чтобы вы передавали ему объекты класса? Что эта библиотека делает с объектами Class, которые вы ей передаете? Создавать объекты? Но если да, то какой конструктор он использует и как он решает, какие аргументы передать? Я не знаю, какую библиотеку вы используете или что она делает, но я предполагаю, что она всегда создает объекты, используя конструктор без аргументов. Однако это не сработает в любом случае для анонимных классов, так как у них нет открытого конструктора (и в любом случае для создания экземпляра любого нестатического внутреннего класса необходимо предоставить ссылку на внешний экземпляр, поэтому конструктор без аргументов отсутствует).).
Вы можете принять имя анонимного класса и позвонить Class.forName("mypackage.MyBaseClass$1")
чтобы получить указатель на анонимный класс. Это даст вам первый анонимный класс, определенный в вашем MyBaseClass
, так что это довольно хрупкий способ обращения к классу.
Я подозреваю, что все, что вы пытаетесь сделать, может быть сделано лучше. Чего вы действительно пытаетесь достичь? Возможно, мы можем предложить способ, который не требует от вас Class
сюда.