我有一个抽象类:
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 ...
}
类CommissionalPoint
和PolarPoint
扩展抽象类:
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
函数来计算路由的长度。我的解决方案有什么问题--我应该如何更改我的泛型(在任何类中)?
首先,请注意,您既要将数据添加到Points
列表中,又要将数据从列表中取出,因此不应使用Extends
或Super
。(另见:胸肌)
private final List<AbstractPoint<?>> points = new ArrayList<>();
接下来,您将看到.dat距(point)
调用出现错误。这是因为没有类型可以用作Distance
方法的类型参数t
,该类型也满足约束t extends abstractPoint
。请注意,Point
的类型是AbstractPoint
,并且AbstractPoint
不能是T
,因为AbstractPoint
不扩展AbstractPoint
。看到问题了吗?
据我所知,您编写distance
的方式不允许您找到两个abstractPoint
之间的距离。其中一个点必须是具体的类型。
事实上,Distance
和VectorTo
实际上并不需要泛型参数。它可以接受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类()));需要:处理程序找到:处理程