如何创建引用嵌套泛型类型的泛型类?
我正在尝试创建一个Comparator类,它可以比较B的内部类型,而不想暴露这些类型的内容。在下面的例子中,我得到一个编译器警告,用于将我的T内部嵌套值原始转换为Comparable:
file2.txt
是否可以使用安全允许铸造来表示内部值?
我尝试过的事情:
创建可比较(不可编译)的通配符:
public class SSCCE {
// Compare my A instances.
class AComparator<T extends B> implements Comparator<T> {
@Override
public int compare(final T o1, final T o2) {
return o1.getValue().compareTo(o2.getValue());
}
}
class A extends B<Integer> {
@Override Integer getValue() { return 1; }
}
class A2 extends B<String> {
@Override String getValue() { return "Test String!"; }
}
abstract class B<T extends Comparable<T>> {
abstract T getValue();
}
public static void main(String[] args) {
SSCCE sscce = new SSCCE();
AComparator<A> comparator = sscce.new AComparator<>();
comparator.compare(sscce.new A(), sscce.new A());
}
}
声明辅助通用参数类型(U),它只是推迟了问题:
class AComparator2<T extends B<? extends Comparable<?>>> implements Comparator<T> {
@Override
public int compare(final T o1, final T o2) {
Comparable<?> o1value = (Comparable) o1.getValue();
Comparable<?> o2value = (Comparable) o2.getValue();
return o1value.compareTo(o2value);
}
}
这个比较器不是要比较A类的两个实例,而是它们内容的一部分。
答案 0 :(得分:7)
通配符解决方案不起作用
class AComparator2<T extends B<?>> {
public int compare(T o1, T o2)
因为T
太宽松了;我们无法确保两个T
可以相互比较 - o1
可能是B<X1>
而o2
是B<X2>
,和X1, X2
是两种不同的类型。
您的第3个解决方案会将T
限制为特定的B<U>
class AComparator3<T extends B<U>, U extends Comparable<U>>
这完美无缺;除了使用网站必须指定U
,即使U
可以从T
中删除。
AComparator3<A, Integer>
^^^^^^^ duh!
这很烦人。之前已经从其他用例中提出了同样的问题。没有好的答案。
幸运的是,在您的情况下,在使用网站的任何地方都不需要U
,因此我们可以简单地使用通配符
AComparator3<A, ?> comparator = sscce.new AComparator3<>();
comparator.compare(sscce.new A(), sscce.new A());
实际上,比较器是Comparator<A>
,这可能就是你所需要的。我们也可以创建一种方便的方法来隐藏new
的丑陋。所以你可能会做类似
Comparator<A> comparator = sscce.comparator();
答案 1 :(得分:3)
您是否考虑过Java 8解决方案?
Comparator<A> comparator = ((t1,t2)-> t1.getValue().compareTo(t1.getValue()));
comparator.compare(sscce.new A(), sscce.new A());
答案 2 :(得分:3)
您可能对比较器感兴趣,比较器应该比较延伸B的类型,但前提是它们具有相同的可比类型。这样的比较器可能看起来像
class AComparator<T extends Comparable<T>> implements Comparator<B<T>> {
@Override
public int compare(final B<T> o1, final B<T> o2) {
return o1.getValue().compareTo(o2.getValue());
}
}
你可以像
一样使用它AComparator<Integer> comparator = sscce.new AComparator<>();
comparator.compare(sscce.new A(), sscce.new A());
comparator.compare(sscce.new A(), sscce.new A2());//compilation error
答案 3 :(得分:1)
为了实现您想要的目标,您需要更改一些内容,我相信如果只实现Generic Comparator。
首先,AComparator应该如下:
pipe = subprocess.Popen('...')
timeout = 10
results = pipe.waitOrTerminate(timeout)
您不需要B类,因为A和A2将直接实施Comparable。只需删除它。
你的A和A2课程:
// Compare my A instances.
class AComparator<T extends Comparable<T>> implements Comparator<T> {
@Override
public int compare(final T o1, final T o2) {
return o1.compareTo(o2);
}
}
请务必阅读Comparable的文档,了解返回值的预期结果。
这有意义吗?
PS:我没有测试这些代码,它们只是我的头脑。
答案 4 :(得分:1)
另一种选择是让B直接实现Comparable,因为你使用getValue()来进行比较。下面摆脱了警告:
import java.util.Comparator;
public class SSCCE {
class A extends B<Integer> {
@Override Integer getValue() { return 1; }
}
class A2 extends B<String> {
@Override String getValue() { return "Test String!"; }
}
abstract class B<T extends Comparable<T>> implements Comparable<B<T>>{
abstract T getValue();
@Override
public int compareTo(B<T> other)
{
return getValue().compareTo(other.getValue());
}
}
public static void main(String[] args) {
SSCCE sscce = new SSCCE();
Comparator.naturalOrder().compare(sscce.new A(), sscce.new A());
}
}
答案 5 :(得分:1)
我想这就是你想要的:
public class SSCCE {
static class BComparator<E extends Comparable<E>> implements Comparator<B<E>> {
@Override
public int compare(final B<E> o1, final B<E> o2) {
return o1.getValue().compareTo(o2.getValue());
}
}
static class A extends B<Integer> {
@Override Integer getValue() { return 1; }
}
static class A2 extends B<String> {
@Override String getValue() { return "Test String!"; }
}
static abstract class B<T extends Comparable<T>> {
abstract T getValue();
}
public static void main(String[] args) {
SSCCE sscce = new SSCCE();
BComparator<Integer> comparator = new BComparator<>();
comparator.compare(new A(), new A());
BComparator<String> comparator2 = new BComparator<>();
comparator2.compare(new A2(), new A2());
}
}
如果您不希望您的比较器能够比较B的两个不同子类的实例(如A2 extends B<String>
和A3 extends B<String>
),则以下工作:
public class SSCCE {
static class BComparator<E extends Comparable<E>, T extends B<E>> implements Comparator<T> {
@Override
public int compare(final T o1, final T o2) {
return o1.getValue().compareTo(o2.getValue());
}
}
static class A extends B<Integer> {
@Override Integer getValue() { return 1; }
}
static class A2 extends B<String> {
@Override String getValue() { return "Test String!"; }
}
static abstract class B<T extends Comparable<T>> {
abstract T getValue();
}
public static void main(String[] args) {
SSCCE sscce = new SSCCE();
BComparator<Integer, A> comparator = new BComparator<>();
comparator.compare(new A(), new A());
BComparator<String, A2> comparator2 = new BComparator<>();
comparator2.compare(new A2(), new A2());
}
}