有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用通配符“重写”类中的方法

我正在编写一个类,它将对存储在MyObject列表中的参数进行耗时的计算。因为我想轻松访问列表的许多特性,所以我决定编写它,扩展列表类型(另一种方法是将列表作为类中的一个字段,并重写我将要使用的所有方法,但这看起来像是过度复杂)。由于计算非常复杂和耗时,而结果完全取决于存储的参数(没有时间影响,没有隐藏的依赖项等),因此我决定缓存结果。因此,我的代码大致如下所示:

public class Calculator extends ArrayList<MyObject> {

   private double Result = Double.NaN; 

   public double getResult() {
        if (Double.isNaN(Result)) {
            Result = CalculateResult();
        }
        return Result;
    }
}

这样,当方法getResult()第一次被调用时,它计算结果,存储结果,然后在后续调用中重用

现在可以通过各种修改来清除缓存列表中的内容。为了实现这一点,我通常会写以下内容:

public void add(MyObject newvalue) {
    super.add(newvalue);
    Result = Double.NaN;
}

但是,它不起作用,因为“super”指的是泛型ArrayList类,所以编译器会产生一个类型错误

在我的级别上,一个明显的技巧是创建一个临时类,它将实现MyObject的ArrayList并使Calculator扩展这个临时类:

public class MyArrayList extends ArrayList<MyObject> {
}

public class Calculator extends MyArrayList {
}

但这看起来又是一次过度复杂化。难道没有更优雅的方法来达到这个效果吗?或者,是否有一种类似于SQL中触发器的机制,每当对列表进行任何修改时,它都会强制我的类清除缓存


共 (2) 个答案

  1. # 1 楼答案

    这是一个很好的例子,说明了composition over inheritance何时对代码设计真正有意义。当您的类只需要有某种类型的List的实例浮动时,它就会被不必要的操作弄得乱七八糟。这还意味着您不需要严格依赖ArrayList实现;例如,如果您的算法调用了一个LinkedList来代替呢

    但是,如果你真的想修复你所拥有的

    首先也是最重要的一点,您出现编译器错误的原因是,就Java而言,尝试重写add方法,但没有完全正确的签名

    正确的签名被指定为boolean add(E),但您正在用void add(E)签名覆盖它。这些类型不匹配,因此您将无法获得成功的重写,并且Java将不会编译该类,如您所见

    接下来,创建更多的类来完成与继承和正确重写ArrayList类相同的事情不会给您带来任何好处;如果有什么区别的话,它将更多地过度复杂化

  2. # 2 楼答案

    方法add应该返回布尔值,因此您需要做的就是

    public boolean add(MyObject newvalue) {
        boolean retVal = super.add(newvalue);
        Result = Double.NaN;
    return retVal ;
    }