当前位置: 首页 > 知识库问答 >
问题:

Java泛型问题--要求测试,提供捕获,反之亦然

何雅惠
2023-03-14

我有一个抽象类:

public abstract class AbstractPoint<PointType extends AbstractPoint<PointType>> {
    public abstract double getX();
    public abstract double getY();
    public abstract double rho();

    // Find the distance between two points
    public final <T extends AbstractPoint<T>> double distance(T other) {
        return vectorTo(other).rho();
    }

    // Find vector from one point to another.
    public abstract <T extends AbstractPoint<T>> PointType vectorTo(T other);

    // other methods ...
}

CommissionalPointPolarPoint扩展抽象类:

public class OrthogonalPoint extends AbstractPoint<OrthogonalPoint> {
    private double x;
    private double y;

    public OrthogonalPoint(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() { return this.x; }

    public double getY() { return this.y; }

    public double rho() { return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); }

    public double theta() { return Math.atan2(this.y, this.x); }

    public <T extends AbstractPoint<T>> OrthogonalPoint vectorTo(T other) {
        return new OrthogonalPoint(other.getX() - this.x, other.getY() - this.y);
    }
}
public class PolarPoint extends AbstractPoint<PolarPoint> {
    private double rho;
    private double theta;

    public PolarPoint(double x, double y) {
        this.rho = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        this.theta = Math.atan2(y, x);
    }

    public double getX() { return this.rho() * Math.cos(this.theta()); }

    public double getY() { return this.rho() * Math.sin(this.theta()); }

    public double rho() { return this.rho; }

    public double theta() { return this.theta; }

    public <T extends AbstractPoint<T>> PolarPoint vectorTo(T other) {
        return new PolarPoint(other.getX() - this.getX(), other.getY() - this.getY());
    }
}

使用这段代码,我可以正确地计算点之间的距离,无论它们是相同类型的(正交的还是极性的)。
现在我添加了另一个名为route:

public class Route {

    private final List<? extends AbstractPoint<?>> points = new ArrayList<>();

    // 'point' in 'this.points.add(point)' underlined red
    public <T extends AbstractPoint<T>> void appendPoint(T point) { this.points.add(point); }

    public <T extends AbstractPoint<T>> void removePoint(T point) { this.points.remove(point);  }

    // 'point' in '.distance(point)' underlined red
    public double routeDistance() {
        return this.points.stream().skip(1).mapToDouble(point ->
                this.points.get(this.points.indexOf(point) - 1).distance(point)).sum();
    }
}

路线是一个有序的点数,其长度定义为序列中点的距离之和。因此,如果一条路由由三个点(p1、p2和p3)组成,则该路由的距离为p1.距离(p2)+p2.距离(p3)
但是,在我的代码中,有些地方(查看route中的注释)下划线为红色:

// in appendPoint function
Required type: capture of ? extends AbstractPoint<?>
     Provided: T

// in routeDistance function
Required type: T
     Provided: capture of ? extends AbstractPoint<?>

我希望能够将任何类型的点添加到points列表中,并调用routeDistance函数来计算路由的长度。我的解决方案有什么问题--我应该如何更改我的泛型(在任何类中)?

共有1个答案

诸福
2023-03-14

首先,请注意,您既要将数据添加到Points列表中,又要将数据从列表中取出,因此不应使用ExtendsSuper。(另见:胸肌)

private final List<AbstractPoint<?>> points = new ArrayList<>();

接下来,您将看到.dat距(point)调用出现错误。这是因为没有类型可以用作Distance方法的类型参数t,该类型也满足约束t extends abstractPoint 。请注意,Point的类型是AbstractPoint ,并且AbstractPoint 不能是T,因为AbstractPoint 不扩展AbstractPoint 。看到问题了吗?

据我所知,您编写distance的方式不允许您找到两个abstractPoint之间的距离。其中一个点必须是具体的类型。

事实上,DistanceVectorTo实际上并不需要泛型参数。它可以接受abstractPoint :

public final double distance(AbstractPoint<?> other) {
    return vectorTo(other).rho();
}

public abstract PointType vectorTo(AbstractPoint<?> other);

现在允许您将abstractPoint 传入Distract

旁注:您当前使用indexof实现routeDistance的效率不是很高,因为它会对列表中的每个点遍历一次列表。您可以使用zip操作来代替。在链接的应答中使用zip方法:

return zip(points.stream(), points.stream().skip(1), AbstractPoint::distance)
    .mapToDouble(x -> x).sum();
 类似资料:
  • 问题内容: 我正在与一起工作,并且在更换单元格工厂时需要通过一个 我所在的班级是A,但我不知道如何使用“捕获”? 我试图创造 但IDEA显示警告 我尝试使用特定的类(例如String)代替“?” 同样,但没有任何帮助。 谁能向我解释如何使用此方法? 谢谢。 编辑: 我收集了一点点信息。该的应该是,但是,TreeTableColumn是我与原始类型创建工作(在库)。 使用原始类型回叫有效。但是还有其

  • 问题内容: 我查看了Java Generics文档 ,发现了这段代码, 我可以理解,我们正在从中获取一个元素并将其设置为另一个。因此,编译器给出了一个错误。我的问题是,它是有道理的,当2列出了不同即这里列出了和是不同的。但是在上面的示例中,和是相同的列表。为什么编译器不够聪明才能看到呢?实施起来难吗? 编辑 :我知道我可以通过辅助方法或使用代替来修复它。只是想知道为什么编译器不为我做。 问题答案:

  • 问题内容: 阅读Java在线教程,我对通配符捕获一无所知。例如: 为什么编译器无法保留分配的安全性?它知道,例如,通过执行带有整数列表的方法,它可以从i.get中获取一个整数值。因此,它尝试将索引0处的Integer值设置为相同的Integer列表(i)。那么,怎么了?为什么要编写通配符助手? 问题答案: 为什么编译器无法保留分配的安全性? 编译器不知道 任何 关于类型中的元素通过定义。通配符并

  • 在阅读Java在线教程时,我对通配符捕获一无所知。例如:

  • 下面的SCCE显示了实现接口标记的两个类(B和C)。对于实现Marker的每个类,都有一个实现泛型处理程序接口的对应类(B_处理程序、C_处理程序)。映射用于关联Pair的类类型。其次是它的关联处理程序。代码按预期执行;但是,我得到一个编译时警告: 警告:[未检查]未检查的强制转换处理程序h1=(处理程序)(dispatch.get(p1.second.get类()));需要:处理程序找到:处理程