【问题标题】:Keep only superclass variables after casting subclass to superclass将子类转换为超类后仅保留超类变量
【发布时间】:2017-08-03 06:10:07
【问题描述】:

我有两节课

基类

public class BaseClass
{
    public int baseClassVariable = 10;
    //like this 10 to 20 variables
}

子类

public class SubClass extends BaseClass
{
    public int subClassVariable = 20;
    //like this 30 to 40 variables
}

还有一个主类:

public class TestMain
{
    public static void main(String[] args)
    {
        Map<String, BaseClass> myData = new HashMap<String, BaseClass>();
        SubClass mydata = new SubClass();
        myData.put("Test", mydata);
        for (Entry<String, BaseClass> data : myData.entrySet())
        {
            System.out.println(data.getKey() + "-" + data.getValue());
        }
    }
}

如您所见,在我的主课中,我有StringMapBaseClass。我的期望是减少内存占用,所以我只需要在内存中保留 BaseClass 变量,这些变量是应用程序中经常使用的数据,但应用程序中需要子类进行一些计算,因此在应用程序中将创建子类。

现在我的问题是归档我的期望的最佳方式(超类和子类)(现在由于继承而无法按预期工作)还是我需要使用不同的机制来实现它。

我的最终目标是在 map 中只保留 BaseClass 变量。

【问题讨论】:

  • 这不会像你想象的那样节省内存。映射中的值仍然是SubClass 对象,即使映射中值的类型是BaseClass。如果您这样做,SubClass 部分不会以某种方式被丢弃。
  • 确实如此。强制转换不会更改对象的类型 - 如果您只想创建一个 BaseClass 对象,您需要明确地执行此操作。
  • @Jesper 是的,即使在将 SubClass 转换为 BaseClass 之后,该类也不会被转换这是正确的,但是我如何才能实现这种类型的要求,还有其他方法吗?
  • 如果您想保留BaseClass 字段并丢弃SubClass 字段,那么继承可能不是您想要的模型。如果 SubClass 数据未绑定到与您的 BaseClass 数据相同的对象中,则很容易丢弃它。
  • @khelwood 但是我的应用程序需要来自 SubClass 和 BaseClass 的全部数据,所以只有我这样使用过,有没有其他方法可以做到这一点而不是拆分这两个类。?

标签: java oop inheritance polymorphism


【解决方案1】:

铸造无法完成您期望完成的工作。

你有几个选择:

  • 将所有要保留的值复制到另一个对象中:

    public PreservedData(WholeBunchOfData data) {
        this.somevar = data.somevar;
        // Copy the values to be preserved manually
    }
    
  • 使用单独的对象将一次性值放入:

    class BaseClass {
        int valueToBePreserved = 29;
        String otherValueToBePreserved = "";
        DisposableObjectContainingDisposableValues someDisposableObj = ...;
    }
    
    class SubClass {
        int disposableValue = 13;
        String someOtherDisposableValue = 47;
    }
    

    完成后,只需将对象设置为 null。

    this.someDisposableObj = null;
    

    很快就会被垃圾回收。

但是,您应该考虑收益是否大于成本。如果只是一些原始值或不是很大的对象,则可能不会有那么多内存。

【讨论】:

    【解决方案2】:

    铸造不会以任何方式修改对象。这是一个编译时操作,它告诉编译器它可以期望一个对象具有特定类型的字段和方法——在这种情况下是一个超类。

    为了将对象从子类类型“转换”为超类类型,您可以做一个接受超类实例的构造函数,如下所示:

    public BaseClass(BaseClass template){
       baseClassVariable=template.baseClassVariable;
       // ... and so forth for all fields
    }
    

    请注意,您可以将子类实例传递给构造函数。由于它只会复制其“已知”字段,因此仍会生成仅包含超类字段的超类实例。

    还要注意,对于非原始类型,简单地复制引用可能很危险,因为原始实例和新创建的实例仍然引用相同的字段。对于复杂的数据结构,您可能需要深度复制引用的字段,例如通过Object.clone()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-03
      • 1970-01-01
      • 1970-01-01
      • 2012-07-22
      • 2013-06-30
      • 1970-01-01
      • 1970-01-01
      • 2017-06-04
      相关资源
      最近更新 更多