反射,创建一个给定int的特定对象

时间:2013-12-19 23:29:36

标签: java reflection mapping

我有Dog.javaCat.javaBird.javaFish.javaNot_Listed.java等类。我还有ID.java只保留一些最终的int映射:

public class ID{
  public static final int CAT = 1;
  public static final int DOG = 3;   // there maybe some integers skipped
  public static final int FISH = 4;   // but all integers are unique
  public static final int BIRD = 6;
  public static final int NOT_LISTED = -1;
}

上面列出的所有类都扩展了Animal.java类。 我需要的是" 6"我需要创建一个Bird对象,给出" 1"我需要创建Cat对象。鉴于" 2"或" 5"我可以返回一个Not_Listed对象或只是抛出一个错误(两个都有效)。我可以使用switch caseHashMap来完成,但我的列表有点长,我不想在列表增长时更新代码。所以我提出了反思,但我不知道该怎么做?

欢迎任何其他有效的解决方案。很抱歉对于反思是noob。提前谢谢。

编辑:ID 必须

3 个答案:

答案 0 :(得分:2)

你不需要反思。

创建一个枚举而不是你的id类,并在枚举中有一个类引用,即:

enum Animal {
     CAT(1, Cat.class),
     DOG(2, Dog.class),
     FISH(3, Fish.class);


     private final Class clazz;
     private final int id;

     Animal(int id, Class clazz) {
        this.id = id;
        this.clazz = clazz;
     }

     public Object generateInstance() {
         return clazz.generateInstance();
     }

     public class getGeneratedClass() {
         return clazz;
     }

     public int getId() {
         return id;
     }
}

这利用了Java的特性,它允许枚举成为功能齐全的类,并记录要在枚举中的每个条目中使用的Class。然后,只要该类具有0参数构造函数,您就可以使用Class按需生成新实例。

要使用它,请执行以下操作:

Animal.DOG.generateInstance() // Returns a Dog object
Animal.CAT.generateInstance() // Returns a Cat object

如果你想从id获得一个类型,你可以在枚举中建立一个HashMap来进行查找,或者只是循环遍历enum.values()寻找一个匹配。

答案 1 :(得分:1)

一种完全不同的方法,所以我将其作为一个单独的答案。

只需创建一个从id到class的Map:

public static final int CAT = 1;
public static final int DOG = 3;   // there maybe some integers skipped
public static final int FISH = 4;   // but all integers are unique
public static final int BIRD = 6;
public static final int NOT_LISTED = -1;

Map<Integer, Class> classMap = new HashMap<>();
classMap.put(CAT, Cat.class);
classMap.put(DOG, Dog.class);
classMap.put(FISH, Fish.class);

public Object generateInstance(int id) {
     // Will throw NullPointerException if id isnt in map, you might want to consider some checks
     return classMap.get(id).generateInstance();
}

那会做你想要的,你真的应该看看我在其他答案中发布的枚举设计 - 从长远来看它会给出更好的结果。

答案 2 :(得分:0)

这样就有了工厂设计模式。您可以在各自的班级中注册每个动物类(例如猫,鱼,狗,鸟等)。

请参阅http://www.oodesign.com/factory-pattern.html

上的课程注册 - 避免反思

你可以拥有一个AnimalFactory,它将ID的地图保存到实现Facotry Method的类。然后,您将在Animal的每个特定实现中注册它。这样AnimalFactory就不需要改变了,只需要添加的每个新Animal都需要注册特定的工厂:

public class Dog extends Animal
{
    ...
    static
    {
        AnimalFactory.instance().registerAnimal(ID.DOG, new DogCreator());
    }
    ...
}

public class DogCreator extends AnimalFactory
{
    //Abstract factory method in AnimalFactory that gets called to return the Animal
    public Animal createAnimal
    {
        return new Dog();
    }
}

开始编辑

您还可以拥有一个使用反射来创建新类的通用动物创建者(假设每个Animal都有一个空构造函数)。这仍然需要您在每个Animal实现中注册您的特定ID:

public class Dog extends Animal
{
    ...
    static
    {
        AnimalFactory.instance().registerAnimal(ID.DOG, Dog.class);
    }
    ...
}

然后AnimalFactory可以使用反射来创建实例:

public Animal createAnimal(ID id)
{
    return animalMap.get(id).newInstance();
}