简体   繁体   English

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

[英]Java - Get correctly casted object from HashMap

I'm developing an application which has several systems (in my case, system is a loadable component in my application which handles a specific task, for example: translation, config handling, audio, etc...). 我正在开发一个具有多个系统的应用程序(在我的例子中,系统是我的应用程序中的可加载组件,它处理特定任务,例如:翻译,配置处理,音频等......)。 These systems share some common methods so I created an interface: 这些系统共享一些常用方法,因此我创建了一个接口:

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

But each system has its own methods corresponding to the task the system implements. 但是每个系统都有自己的方法,对应于系统实现的任务。 Here is two example of my systems 这是我的系统的两个例子

First one stores settings: 第一个存储设置:

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
    }
}

And language system which does translations. 和翻译的语言系统。

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
    }
}

I store the System instances in a static HashMap, because I want to reach them in everywhere in my app. 我将System实例存储在静态HashMap中,因为我想在我的应用程序的任何地方访问它们。 I created a static method to return any systems by a key. 我创建了一个静态方法来通过密钥返回任何系统。

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);
    }
}

If I call the App.getSystem() method, it returns me an Object. 如果我调用App.getSystem()方法,它会返回一个Object。 So If I call... 所以如果我打电话给...

App.getSystem("settings");

... it will return the correct item as an Object. ...它将返回正确的项目作为对象。 But the problem is, I can't call the getSetting() method of SettingsSystem because it tells me that there is no such method. 但问题是,我无法调用SettingsSystem的getSetting()方法,因为它告诉我没有这样的方法。

If I implement it this way: 如果我这样实现它:

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

I can call the initialize() or uninitialize() methods but still no getSettings() method available. 我可以调用initialize()或uninitialize()方法,但仍然没有getSettings()方法可用。

What I want is when I call App.getSystem() method, I want it to return the correct type of object that has in it. 我想要的是当我调用App.getSystem()方法时,我希望它返回其中包含的正确类型的对象。 Example: 例:

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");

How is this possible? 这怎么可能? Thanks in advance. 提前致谢。

UPDATE UPDATE

Based on your help, I decided to declare getter methods for each system: 根据您的帮助,我决定为每个系统声明getter方法:

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

Thank you for your advices! 谢谢你的建议!

You need to cast to the correct type like this: 你需要像这样强制转换为正确的类型:

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

Of course, do this with relevant null checks and so on. 当然,使用相关的null检查等来执行此操作。

I prefer if casting can be avoided however. 如果可以避免铸造,我更喜欢。 Could you keep two seperate maps with the implementing classes instead? 您可以将两个单独的地图与实施类保持一致吗?

Or, since you seem to have several implementations of System , go with Patricia Shanahan's solution #2, which isolates the casting. 或者,由于您似乎有几个System实现,请使用Patricia Shanahan的解决方案#2,它可以隔离转换。

The type of an expression, including the type of the return from a call, is fixed at compile time. 表达式的类型(包括调用返回的类型)在编译时是固定的。 You cannot make the same method, in the same object, have several different return types. 你不能在同一个对象中使用相同的方法,有几种不同的返回类型。

You have two options: 您有两种选择:

  1. Return type Object, and cast in the caller. 返回类型Object,并在调用者中强制转换。
  2. Declare a different getXXXSystem method for each type. 为每种类型声明一个不同的getXXXSystem方法。 getLanguageSystem would have return type LanguageSystem. getLanguageSystem将返回类型LanguageSystem。

That's because System class doesn't have that methods. 那是因为System类没有那些方法。 You would need to explicitly cast to specific classes SettingSystem and LanguageSystem to have this methods available. 您需要显式转换为特定的类SettingSystemLanguageSystem才能使用此方法。

The getSystem() method returns a System instance, so you can only access the method that is defined in the System interface. getSystem()方法返回一个System实例,因此您只能访问System接口中定义的方法。

If you want to access the method that is defined in the concrete implementation class, you must cast the object to that class first 如果要访问具体实现类中定义的方法,则必须首先将该对象强制转换为该类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM