【问题标题】:Assigning a Parent object to a Child object Without casting in Java将父对象分配给子对象而不在 Java 中进行强制转换
【发布时间】:2011-12-16 01:58:41
【问题描述】:

我有一个父接口和一个对象将实现的子接口。我创建了一个子接口,因为我想要一个特定的 VehicleEntity 对象说Truck 将自己添加到Car 中的HashMap。 Truck 将调用 VehicleManager 的 addToCar() 方法,将 Truck 对象添加到 Car 的 hashMap 中。我遇到的问题是CarEntity ce = ve;。 Netbeans 告诉我将 ve 投射到 CarEntity 但我不想。代码行不应该是有效的(假设 for 循环正在查看的对象是 Car 对象)?我该如何解决这个问题?

public interface VehicleEntity {
    getId();
    getSpeed();
    move();
    }

public interface CarEntity extends VehicleEntity{
    addToCar(String c);
}

public class Car implements CarEntity{
HashMap<String, VehicleEntity> cars = new HashMap<String, VehicleEntity>();

    public void addToCar(String c) {
       cars.add(c);
    }
}

public class VehicleManager {
    HashMap<String, VehicleEntity> vehicles = new HashMap<String, VehicleEntity>();

public void reportToCar(String id) {
    for (VehicleEntity ve : ve.values()) {
        if (ve.getId().equals(id)) {
            CarEntity ce = ve; // Issue here
        }
    }
}

【问题讨论】:

  • 那个reportToCar方法属于哪个类?
  • 这里还有更多问题...在addToCar 中,您在HashMap 上调用add。没有这样的方法。您需要使用put(String c, Something s)。那是什么东西?
  • 是的,一开始我有ArrayList,忘记改了

标签: java inheritance casting


【解决方案1】:

真的,这根本不成立。您可以在不强制转换的情况下从特定转移到一般,但不能再返回。例如,您可以将 ArrayList 存储在 List 变量中,但您不能将 List 放入 ArrayList 变量中而不进行强制转换。同样的,你不能在没有明确投射的情况下说它是一辆汽车。

因此,在这种情况下,既然您知道车辆是汽车,请明确地转换为汽车。

【讨论】:

  • 我明白了。我一开始也是这么想的,只是需要一些确认。谢谢!
【解决方案2】:

我不完全确定你想在这里达到什么目的,所以我将首先列出一些我的最佳猜测的修正类...

public interface VehicleEntity {

    public String getId();

    public String getSpeed();

    public void move();

}

public interface CarEntity extends VehicleEntity {

    public void addToCar(String key, CarEntity c);

}

import java.util.HashMap;

public class Car implements CarEntity{ 
HashMap<String, VehicleEntity> cars = new HashMap<String, VehicleEntity>();

    @Override
    public void addToCar(String key, CarEntity car) {
       cars.put(key, this);
    }

    @Override
    public String getId() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getSpeed() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void move() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

...然后向您展示一个使用泛型的酷技巧:

import java.util.HashMap;

public class VehicleManager {

    HashMap<String, VehicleEntity> vehicles =
        new HashMap<String, VehicleEntity>();

    public <T extends VehicleEntity> T report(String id) {
        for(VehicleEntity ve : vehicles.values()) {
            if(ve.getId().equals(id)) {
                @SuppressWarnings("unchecked")
                T ce = (T)ve;
                return ce;
            }
        }
        return null;
    }

    public void test() {

        final Car c = report("test");

    }

}

我已将方法 report 参数化为 T 扩展 VehicleEntity。它将返回 T 那种类型的东西。在方法test() 中使用它时,我们已经声明我们需要Car。现在一些类型推断将继续进行,自动为类型Car 调用方法report。如果地图中具有给定 id 的 VehicleEntity 不是 Car,我们将收到 ClassCastException,因为在该上下文中调用 thet 方法时,我们会尝试强制转换为 Car

【讨论】:

  • 我的问题是关于选角。我不想投,但正如@Micah 所说的那样,这是不可能的。
  • @Dan 有时你只需要投射。但我不确定你的设计到底想达到什么目的,所以也许不同的方法会产生不同的结果。没有演员表。只是不在您当前的结构中。如果您可以为每种类型使用单独的 VehicleManager,则可以避免(使用泛型),但由于情况并非如此,我的建议可以避免为您制作的每个 VehicleEntity 子类型使用单独的方法。需要记住的一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 1970-01-01
相关资源
最近更新 更多