是否可以使用字符串的内容来转换对象?

Is it possible to cast an Object using the contents of a String?

回顾笔记:这个问题大部分都没有多大意义。这是我的第一个问题,充满了关于抽象 classes 如何工作的错误假设。我不会删除它,因为可以从中学到一些东西,但我知道没有太多有用的信息可以从中提取。


你需要知道的事情:

我有一个名为 Component 的抽象基础 class...

public abstract class Component
{
    public abstract void doStuff();
}

我有一些组件的子classes...

public class Camera extends Component
{
    @Override
    public void doStuff() {
        //method specific to Camera objects
    }
}

public class Transform extends Component
{
    @Override
    public void doStuff() {
        //method specific to Transform objects
    }
}

问题:

我需要一种方法可以遍历 HashMap 中的每个组件并为每个组件调用适当的 "doStuff();" 方法。

我的第一个方法是做这样的事情...

示例驱动程序 #1:

public class Foo
{
    HashMap<String, Component> components;

    public Foo()
    {
        components = new HashMap<String, Component>();
        components.put("Camera", new Camera());
        components.put("Transform", new Transform());
    }

    public void bar()
    {
        //Assuming I don't know exactly what components are in the HashMap...
        //Iterate through all components,
        //Cast them to appropriate type,
        //Call "doStuff();" in all components.

        Iterator iterator = components.iterator();
        while(iterator.hasNext())
        {
            Entry componentPair = (Entry) iterator.next();
            Component component = (Component) componentPair.getValue();
            component.doStuff();
        }
    }
}

但是这段代码是错误的。 在上面的示例中,每次调用 component.doStuff(); 时,我都会调用组件基 class 中的空 doStuff 方法。因此subclassdoStuff();方法的none其实是调用了.

记住,我不想将任何内容转换为组件;我只想将 转换为 Component.

的 subclasses

对于我的第二种方法,我尝试使用相关的字符串来转换组件...

示例驱动程序#2:

...
while(iterator.hasNext());
{
    Entry componentPair = (Entry) iterator.next();
    String mapKey = componentPair.getKey().toString();
    Object mapValue = componentPair.getValue();
    Object component = Class.forName(mapKey).cast(mapValue);
    component.doStuff();
}
...

但是这个 不会编译 因为组件被视为对象类型并且 doStuff(); 不是对象 class.

最后的想法:

是否有不需要重新构建代码的解决方案? 我有可能 designed/structured 这个程序真的很糟糕,因为我很确定 Java 无法进行动态转换。 如果是这样,谁能告诉我解决问题的好方法?也许改用接口?

你的第一个方法就是要走的路。

假设您有您描述的 HashMap:

HashMap<String, Component> components = new HashMap<String, Component>();
components.put("Camera", new Camera());
components.put("Transform", new Transform());

如果需要键,可以遍历Map的EntrySet。如果您只想调用函数,可以使用地图的 values() 函数。这样你也不需要迭代器结构,但你可以使用 for each 循环,我认为这看起来更好。

for(Component nextComponent : components.values()){
    // do some other stuff here
    nextComponent.doStuff();
}

抽象方法不会被调用,你也不需要在这里强制转换任何东西,因为编译器已经知道要调用哪个函数。

据我所知,HashMap没有iterator()方法。

这个方法可以完美地工作,而是在 entrySet 上创建迭代器。

Iterator<Entry<String, Component>> iterator = components.entrySet().iterator();
while (iterator.hasNext()){
    iterator.next().getValue().doStuff();
}

或者如果您只需要值

Iterator<Component> iterator = component.values().iterator();
while (iterator.hasNext()){
    iterator.next().doStuff();
}

在运行时,Component component 将是 CameraTransform 的实例或 Component 抽象 class 的任何其他实现。考虑到多态性(我建议你看一些关于它的文章,比如 https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html),覆盖的 doStuff() 方法将被调用。您不需要将 Component 实例显式转换为 CameraTransform,因此您的第一个示例就是要走的路。

   for (Component component : components.values()){
         // component may be a Camera or Transform. It doens't matter; override will be called.
        component.doStuff();
    }