在java中创建一个动态类

时间:2016-12-01 05:05:02

标签: java reflection interface dynamic-class

我正在研究一个问题,其中不同的动物类型从Animal界面实现相同的talk()方法 如果你看一下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");
        }
    }
}

我在谷歌搜索,了解它可以通过反思来完成。但不知道如何。如果可能的话,你能帮我解决这个问题吗?提前谢谢!

4 个答案:

答案 0 :(得分:3)

您知道运行时类生成非常复杂,并且不适合初学者使用该语言。这将是一个使用地图和匿名类的绝佳方案。

Html.Kendo().TreeView()
                .Name("TreeViewTemplateBiding")                        
                .TemplateId("TreeViewTemplate")                             
                        .BindTo((IEnumerable<OrgChart.Models.NodeViewModel>)ViewBag.Tree, (Kendo.Mvc.UI.Fluent.NavigationBindingFactory<TreeViewItem> mappings) =>
                           {
                               mappings.For<OrgChart.Models.NodeViewModel>(binding => binding.ItemDataBound((item, node) =>
                               {
                                   item.Id = node.Id;
                                   item.Text = node.Title;
                                   //item.Expanded = node.Expanded;
                               })
                       .Children(node => node.Children));
                           })                               
   )

如果您确实坚持真正的运行时类生成,或者您对它的工作原理感到好奇,请查看ByteBuddy

答案 1 :(得分:2)

老问题,但这里是如何创建类...对我来说,简单的方法是使用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中创建了一个类。我还在这个类中添加了一个方法,并通过反射调用它。

希望它有所帮助。

  

请记住要在生成的类中使用的任何内容   不是导入,因此您必须使用完全限定名称。

答案 2 :(得分:0)

你必须定义狗类

class Dog implements Animal {

    @Override
    public void talk() {
        System.out.println("woof");
    }
}

并将if else添加到AnimalType

} else if ("loyal".equals(criteria)) {
      return new Dog();
}

答案 3 :(得分:0)

Java不支持在运行时创建类。然而,有更好的方法来实现你想要的东西。我会提出两个。

首先,您可以创建一个AnimalType类,其中包含有关物种的所有共享行为。然后,您可以使用Animal类,将AnimalType作为构造函数参数。

其次,您可以使用prototype设计模式。在这种情况下,Animal类需要clone方法从原型中创建新动物。然后,工厂类可以拥有原型列表,并使用您想要的任何逻辑来选择要克隆的正确原型。

如果您需要其他任何选项的更多详细信息或示例代码,请在下面进行评论。