在 java 中创建动态 class
Create a dynamic class in java
我正在解决不同动物类型从 Animal 接口实现相同 talk() 方法的问题。
如果您查看 getAnimal()
方法,您会发现,当一种新的动物被添加到程序中时,该方法的内部也必须更改。
我想通过对 Animal 进行子类化来添加新动物,而不更改现有 类.
中的任何内容
比如添加一个动物"Dog", criteria="loyal";谈话="woof".
你能告诉我,这怎么可能吗?下面是我的代码:
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 上搜索了一下,了解到可以通过反射来完成。但是不知道怎么办。如果可能的话,你能帮我解决这个问题吗?提前致谢!
你要定义狗class
class Dog implements Animal {
@Override
public void talk() {
System.out.println("woof");
}
}
并将 if else 添加到 AnimalType
} else if ("loyal".equals(criteria)) {
return new Dog();
}
请注意,运行时 class 生成非常复杂,不建议初学者使用该语言。这将是使用匿名地图的绝佳方案 classes.
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);
}
}
如果您确实坚持真正的运行时 class 生成,或者如果您对它的工作原理感到好奇,请查看 ByteBuddy。
Java 不支持在运行时创建 class。但是,确实有更好的方法可以在这里实现您想要的。我推荐两个。
首先,您可以创建一个 AnimalType
class,其中包含关于一个物种的所有共享行为。然后你可以有一个 Animal
class 将 AnimalType
作为构造函数参数。
其次,您可以使用 prototype 设计模式。在这种情况下,Animal
class 需要一个 clone
方法来从原型创建一个新动物。工厂 class 然后可以有一个原型列表,并使用您想要的任何逻辑来选择要克隆的正确原型。
如果您需要这些选项的更多详细信息或示例代码,请在下方评论。
老问题,但这里是如何创建 class...对我来说,简单的方法是使用 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 中创建了一个 class。我还在此 class 中添加了一个方法,并通过反射调用了它。
希望对您有所帮助。
Just keep on mind whatever you want to use in generated class, there
are NOT imports, so you have to use fully-qualified names.
我正在解决不同动物类型从 Animal 接口实现相同 talk() 方法的问题。
如果您查看 getAnimal()
方法,您会发现,当一种新的动物被添加到程序中时,该方法的内部也必须更改。
我想通过对 Animal 进行子类化来添加新动物,而不更改现有 类.
中的任何内容
比如添加一个动物"Dog", criteria="loyal";谈话="woof".
你能告诉我,这怎么可能吗?下面是我的代码:
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 上搜索了一下,了解到可以通过反射来完成。但是不知道怎么办。如果可能的话,你能帮我解决这个问题吗?提前致谢!
你要定义狗class
class Dog implements Animal {
@Override
public void talk() {
System.out.println("woof");
}
}
并将 if else 添加到 AnimalType
} else if ("loyal".equals(criteria)) {
return new Dog();
}
请注意,运行时 class 生成非常复杂,不建议初学者使用该语言。这将是使用匿名地图的绝佳方案 classes.
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);
}
}
如果您确实坚持真正的运行时 class 生成,或者如果您对它的工作原理感到好奇,请查看 ByteBuddy。
Java 不支持在运行时创建 class。但是,确实有更好的方法可以在这里实现您想要的。我推荐两个。
首先,您可以创建一个 AnimalType
class,其中包含关于一个物种的所有共享行为。然后你可以有一个 Animal
class 将 AnimalType
作为构造函数参数。
其次,您可以使用 prototype 设计模式。在这种情况下,Animal
class 需要一个 clone
方法来从原型创建一个新动物。工厂 class 然后可以有一个原型列表,并使用您想要的任何逻辑来选择要克隆的正确原型。
如果您需要这些选项的更多详细信息或示例代码,请在下方评论。
老问题,但这里是如何创建 class...对我来说,简单的方法是使用 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 中创建了一个 class。我还在此 class 中添加了一个方法,并通过反射调用了它。
希望对您有所帮助。
Just keep on mind whatever you want to use in generated class, there are NOT imports, so you have to use fully-qualified names.