Java &引用;压倒一切;类中带有通配符的方法

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

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

public class Calculator extends ArrayList<MyObject> {

   private double Result = Double.NaN; 

   public double getResult() {
        if (Double.isNaN(Result)) {
            Result = CalculateResult();
        }
        return Result;
    }
}
但是,它不起作用,因为“super”指的是泛型ArrayList类,所以编译器会产生一个类型错误

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

public class MyArrayList extends ArrayList<MyObject> {
}

public class Calculator extends MyArrayList {
}
公共类MyArrayList扩展了ArrayList{
}
公共类计算器扩展MyArrayList{
}

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

这是一个很好的例子,说明什么时候对代码设计真正有意义。当您的类只需要一个浮动的
列表
实例时,它就会被不必要的操作弄得乱七八糟。这还意味着您不必严格依赖于
ArrayList
实现;例如,如果您的算法调用的是
LinkedList
,那会怎么样

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

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

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


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

这是一个很好的例子,说明什么时候对代码设计真正有意义。当您的类只需要一个浮动的
列表
实例时,它就会被不必要的操作弄得乱七八糟。这还意味着您不必严格依赖于
ArrayList
实现;例如,如果您的算法调用的是
LinkedList
,那会怎么样

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

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

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


接下来,创建更多的类来完成与继承和正确重写
ArrayList
类相同的任务不会给您带来任何好处;如果有什么不同的话,它将是一个超复杂的方法。

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

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

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

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

不要扩展列表实现。这将污染您的API,并永远将类连接到该特定实现。将其用作字段并在类上实现
List
接口,然后将所需的方法委托给用作字段的列表实现实例。这有点冗长,但对你的类的用户来说更灵活、更干净。非常感谢你们的及时回复。您的示例确实解决了编译问题。然而,实际上,我似乎也需要重新思考代码设计背后的原理。不要扩展列表实现。这将污染您的API,并永远将类连接到该特定实现。将其用作字段并在类上实现
List
接口,然后将所需的方法委托给用作字段的列表实现实例。这有点冗长,但对你的类的用户来说更灵活、更干净。非常感谢你们的及时回复。您的示例确实解决了编译问题。然而事实上,我似乎也需要重新思考代码设计背后的原理。这将修复编译器错误,我投了赞成票。然而,关于更喜欢组合而不是继承的其他评论是:最好将ArrayList作为成员变量而不是超类。这将修复编译器错误,我投了赞成票。然而,关于更喜欢组合而不是继承的其他评论是:最好将ArrayList作为成员变量,而不是作为超类。