Java - 从HashMap中获取正确的转换对象

时间:2013-05-07 08:54:16

标签: java interface casting hashmap

我正在开发一个具有多个系统的应用程序(在我的例子中,系统是我的应用程序中的可加载组件,它处理特定任务,例如:翻译,配置处理,音频等......)。这些系统共享一些常用方法,因此我创建了一个接口:

public interface System {
    public void initialize();
    public void uninitialize();
}

但是每个系统都有自己的方法,对应于系统实现的任务。这是我系统的两个例子

首先存储设置:

public class SettingsSystem implements System {
    @Override
    public void initialize() {
        // few lines of code here
    }

    @Override
    public void uninitialize() {
        // few lines of code here
    }

    public Object getSetting(String key) {
        // returns a setting
    }
}

进行翻译的语言系统。

public class LanguageSystem implements System {

    @Override
    public void initialize() {
        // few lines of code here
    }

    @Override
    public void uninitialize() {
        // few lines of code here
    }

    public void setLanguage(String language) {
        // sets language
    }

    public boolean load( String name) {
        // loads a file
    }

    public String translate(String key) {
        // returns translation of a key
    }
}

我将System实例存储在静态HashMap中,因为我想在我的应用程序的任何地方访问它们。我创建了一个静态方法来通过密钥返回任何系统。

public class App {
    // note: System is the System interface I created
    private static Map<String, System> systems = new HashMap<String, System>();

    public static Object getSystem(String key) {
        return systems.get(key);
    }
}

如果我调用App.getSystem()方法,它会返回一个Object。所以,如果我打电话给...

App.getSystem("settings");

...它会将正确的项目作为对象返回。但问题是,我无法调用SettingsSystem的getSetting()方法,因为它告诉我没有这样的方法。

如果我这样实现:

public static System getSystem(String key) {
    return systems.get(key);
}

我可以调用initialize()或uninitialize()方法,但仍然没有getSettings()方法可用。

我想要的是当我调用App.getSystem()方法时,我希望它返回其中包含的正确类型的对象。例如:

App.getSystem("settings"); // I want it to return a SettingsSystem object
// So I can do:
String width = App.getSystem("settings").getSetting("width");

App.getSystem("language"); // I want it to return a LanguageSystem object
// So I can do:
String welcome = App.getSystem("language").translate("hello_world");

这怎么可能?提前谢谢。

更新

根据您的帮助,我决定为每个系统声明getter方法:

public SettingsSystem getSettingsSystem() {
    return (SettingsSystem) system.get("settings");
}

感谢您的建议!

4 个答案:

答案 0 :(得分:3)

你需要像这样强制转换为正确的类型:

SettingsSystem settingSystem = null;
System system = App.getSystem("settings");
if (system instanceof SettingsSystem) {
    settingSystem = (SettingSystem) system;
}
settingSystem.getSetting("width");

当然,使用相关的null检查等来执行此操作。

我更喜欢可以避免铸造。你可以用实现类保留两个单独的地图吗?

或者,既然您似乎有多个System的实现,请使用 Patricia Shanahan的解决方案#2来隔离转换。

答案 1 :(得分:2)

表达式的类型,包括调用返回的类型,在编译时是固定的。你不能在同一个对象中使用相同的方法,有几种不同的返回类型。

您有两种选择:

  1. 返回类型对象,并在调用者中强制转换。
  2. 为每种类型声明不同的getXXXSystem方法。 getLanguageSystem将返回类型LanguageSystem。

答案 2 :(得分:1)

那是因为System类没有那种方法。您需要明确转换为特定类SettingSystemLanguageSystem才能使用此方法。

答案 3 :(得分:1)

getSystem()方法返回一个System实例,因此您只能访问System接口中定义的方法。

如果要访问具体实现类中定义的方法,则必须先将该对象强制转换为该类