2

当我学习它时,我正在遵循对 Java 接口进行编码的实践。我有一个Function具有 executeFunction() 方法的接口。但我想让这个方法通用。所以客户端可以传入一个字符串、布尔值、整数、双精度等列表来对它们运行聚合计算。

但是我对泛型没有很好的掌握,所以我想要一些建议和解释我在编码过程中的设计方法实际上能够做什么。我正在考虑有一个 StatsFunctions 和 ArithmeticFunctions 具体实现类,可以注入其他类以使用它们的功能。(排序尝试策略模式)。

这是我的代码:

import java.util.List;

public interface Function {

    public <T> double executeFunction(List<T> vector);

}

问题:

1)。我如何使用/更改上面的这个接口以使其尽可能通用和动态?如果你能提供一些使用它的例子,这将对我的学习有很大的帮助。2)。为什么我不能执行以下操作?我收到一条错误消息:The operator "+" is undefined for the argument type T.

public class ArithmeticFunctions implements Function {
    @Override
    public <T> double executeFunction(List<T> vector) {
        int retVal = 0;
        for (int i = 0; i < vector.size(); i++) {
            retVal = vector.get(i) + retVal;
        }
        return retVal;
    }

}

先感谢您。

4

3 回答 3

2

更好::

public interface Function<F, T> {
    T apply(F input);
}

像这样使用它::

Function<Integer, Integer> doubleMyInput = new Function<Integer, Integer>() {
        @Override
        public Integer apply(Integer input) {
            return input * 2;
        }
};

第二个问题的答案没有那么简单。您看到的错误是类型擦除的结果(这就是泛型在 JVM 上的实现方式)。基本上,您的泛型函数声明等同于以下内容::

public <T extends Object> double executeFunction(List<T> vector);

Java 运行时看不到你的类型声明,它只看到对象。

为了更清楚地理解,让我们假设我们在 java 1.4 中工作,当时不存在泛型。您的界面将如下所示::

public interface MyFunction {

    public double executeFunction(List vector);
}

和实施::

public class ArithmeticFunction implements MyFunction {

    public double executeFunction(List vector) {
        double retVal = 0;
        for (int i = 0; i < vector.size(); i++) {
            retVal += (((Double)vector.get(i))).doubleValue();
        }
        return retVal;
    }
}

请注意演员表,因为实际上没有其他方法可以检索该值。

然后你可以这样做::

ArithmeticFunction af = new ArithmeticFunction();
// Good
af.executeFunction(new ArrayList(Arrays.asList(new Double[] {new Double(1), new Double(2)})));

但是,这也是可能的,并且会在运行时为您提供 ClassCastException ::

// Bad !!
af.executeFunction(new ArrayList(Arrays.asList(new String[] {"A", "B", "C"})));

因此,总而言之,在您的实现之间进行并行处理(并了解运行时发生的情况)::

// does not compile
public class ArithmeticFunction implements MyFunction {

    public double executeFunction(List<Integer> vector) {
        int retVal = 0;
        for (int i = 0; i < vector.size(); i++) {
            retVal = vector.get(i) + retVal;
        }
        return retVal;
    }
}

和上面的例子。

哦,要解决您的问题,您必须这样做::

public interface Function<T> {

    public double executeFunction(List<T> vector);
}

我知道这里介绍的一些概念可能不清楚,所以最好的办法是使用泛型教程来加快速度。

于 2013-10-12T02:05:21.413 回答
1

TL;DR:放入<T>方法意味着在调用方法时将知道列表的实际类型。<T>在接口上意味着在声明类时列表的类型是已知的。

本声明

public interface Function {
    public <T> double executeFunction(List<T> vector);
}

意思是:

该方法executeFunction()可以输入任何类型的列表,并double从中计算出a。

调用此方法的人可以合法地通过你List<Double>List<Integer>等等List<String>。这可能不是你想要的。

如果您像这样更改接口声明:

public interface Function<T> {
    public double executeFunction(List<T> vector);
}

你可以用这种方式声明你的类:

public class Summation implements Function<Double> {
    public double executeFunction(List<Double> vector) {
        // ...        
    }
}

现在您确定其中的每个元素vector都是 a Double,因此您可以安全地总结它们。

于 2013-10-12T07:43:02.187 回答
0
public interface Function<T> {
  public T executeFunction(List<T> vector);
}

读作:类型为 T 的公共接口函数

这就是函数executeFunction返回您在上面声明的类型 T 的原因。

请注意,T 始终是 Object,但 Java 可以通过自动装箱处理原始类型(int、double)。

于 2013-10-11T22:52:25.523 回答