2013-02-24 61 views
1

的地图我需要初始化一个连接对象的XML定义豆类外径不同的类型。我有目录结构:地图不同类型

data \ 
|_ plant \ 
| |_ pine.xml 
| |_ cucumber.xml 
|_ animal \ 
| |_dog.xml 
| |_cat.xml 
|_ fungus \ 
... 

我想按顺序将其存储在两级地图中:第一级地图包含第二级地图。每个二级地图都包含一种类型的对象(类植物/动物/真菌......)。每个类扩展了具有一些常用字段和方法(名称/ getName()/ setName(),desc/getDesc()/ setDesc(),toString(),equals()等的Dict类。 ,以方便所有这些对象我想有工厂方法Dict.fabricateAll(创建)这里的问题是:如何使他们有精确的类型参数创建第二级地图,我不想HashMap的<字符串,快译通>但HashMap的<字符串,植物>,HashMap的<字符串,动物>等

现在我有以下代码:

public static Map<String, Map<String, ? extends Dict>> fabricateAll() { 
    File topDir = new File(Dict.defDir); 
    File[] subDirs = topDir.listFiles(); 
    Map<String, Map<String, ? extends Dict>> dicts = new HashMap<>(subDirs.length); 

    String type; 
    String handle; 
    Map<String, ? extends Dict> dict; 

    for (File subDir : subDirs) { 
     type = subDir.getName(); 
     File[] xmlFiles = subDir.listFiles(new FilenameFilter() {public boolean accept(File dir, String name) { return name.toLowerCase().endsWith(".xml"); }}); 
     dict = new HashMap<>(xmlFiles.length); 

     for (File defFile : xmlFiles) { 
      handle = defFile.getName(); 
      handle = handle.substring(0, handle.lastIndexOf('.')-1); 

      try { 
       Class c = Class.forName(type); 
       Constructor bob = c.getConstructor(Class.forName("java.lang.String")); 
       dict.put(handle, bob.newInstance(handle)); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     dicts.put(type, dict); 
    } 
    return dicts; 
} 

但有一个与线的一个问题: dict.put(手柄,bob.newInstance(手柄));

错误消息:“方法把接口Map < K,V >不能被应用到给定的类型的要求:字符串,CAP#1实测值:字符串,对象

是的,这的newInstance()生成对象和或许应该有一些投,但到什么?我不想只是“(字典)”在这里,我更喜欢“(植物)”,“(动物)” ......为合适的。那怎么办?

+0

你返回一个'地图<字符串,地图<字符串?扩展Dict >>'。因此,客户端代码无法知道地图是否包含Plant,Cat或其他内容。它只知道它们是Dict的实例。所以把它投给Dict,一切都会好起来的。也就是说,我不会使用反射来做到这一点,而是工厂(每种字典的一个工厂),这将允许做你想做的事情。 – 2013-02-24 17:36:58

+0

但是动物可以运行()而植物不能。如果我将它转换为Dict,我不可能首先调用run(),而不是手动投射到Animal。 至于办法“每一个快译通工厂”:你的意思是我应该在的,而不是调用每个快译通亚型和公共静态编造(字符串处理)'“bob.newInstance(句柄)”做: 字典。 put(handle,c.getMethod(“fabricate”,Class.forName(“java.lang.String”)))? 这给出了相同的错误。 – Forseti 2013-02-24 17:56:52

+0

当你有一个Map ',你无法知道地图包含什么。你所能做的就是测试这个值是植物还是动物的一个实例(使用'instanceof'),并将这个值转换为植物或动物。那么你将Map作为'Map '获得了什么,因为你将它作为'Map 返回?扩展Dict>'。你的工厂理念确实是一个解决方案。您将需要返回Plant或Animal(取决于类)的方法,并且您需要地图的类型为Map 或Map 类型,具体取决于在目录中。 – 2013-02-24 18:04:24

回答

1

将对象转换为字典这是多态的好处 - 你不必引用特定的子类,你可以编写代码时只引用单个基类Dict,这会给你:

  • 一)松耦合 - 在特定的子类
  • B)Exetensibility没有编译时依赖 - 你可以添加的子类,而无需修改此代码。

是的,有办法实现你问什么(大switch语句想到的),但没有,我会推荐。