【问题标题】:Java: Generic Interface, instance chosen at runtimeJava:通用接口,在运行时选择的实例
【发布时间】:2013-08-13 14:54:10
【问题描述】:

我有以下简单的界面:

public interface ISimmilarityMeasure<T extends ResourceDescriptor> {
    public double getSim(T s, T t);
}

和类似的实现

public class NormalizedLevenstheinSim implements
             ISimmilarityMeasure<SimpleResourceDescriptor> { ... }

public class JaccardCommentsSim implements
             ISimmilarityMeasure<LabelsCommentsResourceDescriptor> { ... }

SimpleResourceDescriptorLabelsCommentsResourceDescriptor 都扩展

public abstract class ComparableResourceDescriptor
             implements ResourceDescriptor 

在运行时,我调用方法

public static ISimmilarityMeasure<? extends ResourceDescriptor> getSimInstance(){ }

这将返回一个依赖于特定 ResourceDescriptor 实例的 ISimilarityMeasure 实例“sim”。

我还创建了一个数组 ResourceDescriptor[] candidates,它将在运行时保存特定 ISimilarityMeasure 对象所需的 ResourceDescriptor 类型的实例。

但是,如果我尝试调用 sim.getSim(candidates[0], candidates[1]),编译器会告诉我

"capture#3-of ? extends ResourceDescriptor ... is not applicable for the arguments (ResourceDescriptor ... "

我使用 eclipse,如果我查看 sim 的可用方法,它会显示 getSim(null s, null t)。 我不明白为什么会这样。如果编译器不清楚,getSim 必须期待任何 ResourceDescriptor 并且 candidates 中的每个对象都是 ResourceDescriptor 并因此允许调用?如果特定的 ISimmilarityMeasure 需要某种类型的 ResourceDescriptor 但被交给了不同的 ResourceDescriptor,那么它在运行时不应该是一个例外吗?

【问题讨论】:

  • 你能展示一些你的代码的实际流程吗?目前,您所说的一切都在我脑海中混杂。我无法掌握所有这些。一方面,我无法理解sim() 的实际签名。您已经向我们展示了 3。
  • 由于ISimmilarityMeasure接口是通用的,getSim(..)的签名也是通用的。例如,在接口中它是 getSim(T s, T t),而在 NormalizedLevenstheinSim 中,它是 getSim(SimpleResourceDescriptor s, SimpleResourceDescriptor t)。 “sim”是 ISimilarityMeasure 的一个实例。具体实现(例如 NormalizedLevenstheinSim 或 JaccardCommentsSim)在运行时选择。我承认,这有点令人困惑:)
  • 好吧,我说的是返回类型。在界面中你有double,然后在中间是ISimmilarityMeasure&lt;? extends ResourceDescriptor&gt;
  • 对不起,这只是一个错误的命名 - 中间的一个(我将它重命名为“getSimInstance”)是一个静态工厂方法来获得一个实现。 double getSim(T s, Tt)是接口的实际计算方法。

标签: java generics wildcard bounded-wildcard


【解决方案1】:

getSimInstance() 将为某些类型 X 返回一个类型为 ISimmilarityMeasure&lt;X&gt; 的对象。关于X,我们所知道的只是它继承自ResourceDescriptor。在这个对象上,你调用getSim(ResourceDescriptor, ResourceDescriptor)。但是,它不期望 ResourceDescriptor 参数,而是期望 X 参数。

虽然X 始终是ResourceDescriptor,但不能保证ResourceDescriptorX,因此您的编译器拒绝接受它。

【讨论】:

  • 好的,我明白了。对于我正在尝试做的事情,是否有一个很好的替代方案,或者我应该参数化,例如,使用 的 NormalizedLevenstheinSim 并在 getSim() 方法中执行instanceof SimpleResourceDescriptor 检查?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-09
相关资源
最近更新 更多