Создать динамический класс в Java
Я работаю над проблемой, когда разные типы животных реализуют один и тот же метод talk() из интерфейса Animal.
Если вы посмотрите на getAnimal()
В этом методе вы можете видеть, что когда в программу добавляется новый вид животных, внутри этого метода также необходимо изменить.
Я хочу добавить новых животных, просто создав подклассы Animal, не меняя ничего в уже существующих классах.
Например, добавить животное "Собака", критерий = "верный"; говорить = "гав".
Не могли бы вы сказать мне, как это возможно? Ниже мой код:
interface Animal {
public void talk();
}
class Lion implements Animal {
@Override
public void talk() {
System.out.println("ROARRRRR");
}
}
class Mouse implements Animal {
@Override
public void talk() {
System.out.println("SQUEEEEEAK");
}
}
class Bison implements Animal {
@Override
public void talk() {
System.out.println("BELLOWWWWW");
}
}
class AnimalType {
public static Animal getAnimal(String criteria) {
// I refactor this method
if (criteria.equals("small")) {
return new Mouse();
} else if (criteria.equals("big")) {
return new Bison();
} else if (criteria.equals("lazy")) {
return new Lion();
}
return null;
}
}
public class AnimalExamples {
public static void main(String[] args) {
AnimalType.getAnimal("small").talk();
AnimalType.getAnimal("big").talk();
AnimalType.getAnimal("lazy").talk();
// how to add an animal "Dog" here, criteria="loyal"; talk="woof"
AnimalType.getAnimal("loyal").talk();
try {
AnimalType.getAnimal("small").talk();
} catch (Exception ex) {
System.out.println("Animal does not exists");
}
}
}
Я искал в Google, понял, что это можно сделать с помощью отражения. Но не знаю как. Если возможно, не могли бы вы помочь мне с этим, пожалуйста? Заранее спасибо!
4 ответа
Просто вы знаете, что генерация классов во время выполнения чрезвычайно сложна и не рекомендуется для начинающих изучать язык. Это был бы отличный сценарий использования карты анонимных классов.
class AnimalType {
private static final Map<String, Animal> animals = new HashMap<String, Animal>();
static {
// Populating map with default animals
addAnimal("big","BELLOWWWWW"); // bison
addAnimal("small","SQUEEEEEAK"); // mouse
addAnimal("lazy","ROARRRRR"); // lion
addAnimal("loyal","WOOF "); // dog
}
public static void addAnimal(String criteria, final String sound) {
// Assigning a anonymous implementation of animal to the given criteria
animals.put(criteria, new Animal() {
@Override
public void talk() {
System.out.println(sound);
}
});
}
public static Animal getAnimal(String criteria) {
// Returning an animal from the animals map
return animals.get(criteria);
}
}
Если вы действительно настаиваете на истинном генерировании классов во время выполнения или если вам интересно, как это работает, проверьте ByteBuddy.
Старый вопрос, но вот как создать класс... Для меня проще всего использовать Javassist. Я создал небольшой пример здесь: http://hrabosch.com/2018/04/08/generate-class-during-runtime-with-javassist/
Но вот главный момент:
public static Class generateClass(String className, String methodName, String methodBody)
throws CannotCompileException {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(className);
StringBuffer method = new StringBuffer();
method.append("public void ")
.append(methodName)
.append("() {")
.append(methodBody)
.append(";}");
cc.addMethod(CtMethod.make(method.toString(), cc));
return cc.toClass();
}
Итак, что я сделал... Через Javassist я сделал класс в ClassPool. Также я добавил метод в этот класс и через рефлексию вызвал его.
Надеюсь, поможет.
Просто имейте в виду, что вы хотите использовать в сгенерированном классе, импорт НЕ выполняется, поэтому вы должны использовать полные имена.
Java не поддерживает создание класса во время выполнения. Однако есть действительно лучшие способы достижения того, что вы хотите здесь. Я предложу два.
Во-первых, вы могли бы создать AnimalType
класс, который содержит все общее поведение о виде. Вы могли бы тогда иметь Animal
класс, который принимает AnimalType
в качестве параметра конструктора.
Во-вторых, вы можете использовать шаблон дизайна прототипа. В этом случае Animal
класс понадобится clone
Способ создания нового животного по прототипу. Затем фабричный класс может иметь список прототипов и использовать любую логику, которую вы пожелаете, чтобы выбрать правильный прототип для клонирования.
Прокомментируйте ниже, если вы хотите получить дополнительную информацию или образец кода для любого из этих вариантов.
Вы должны определить класс собаки
class Dog implements Animal {
@Override
public void talk() {
System.out.println("woof");
}
}
и добавьте if if к AnimalType
} else if ("loyal".equals(criteria)) {
return new Dog();
}