【发布时间】:2015-07-08 15:05:40
【问题描述】:
我使用泛型来抽象出 Comparable 数据类型,如下面提供的代码所示。此案例源于一个 Java Swing 组件,特别是尝试将表模型调整为使用泛型。
我有一个可行的解决方案来解决这个问题(下面的案例 3A)。但是,在获得该解决方案的过程中,当我将类签名从 T extends Comparable<T> 更改为 T extends Comparable<? super T> 时,我对编译器的行为感到困惑。
为什么编译器希望 Comparable 成为原始类型(下面的案例 3A)?我希望类签名能够工作(案例 6A,Class<T extends Comparable<? super T>>),但它需要强制转换并在使用 if (type == Boolean.class) 时导致编译器错误。
为什么情况 2B、3A/B 和 4A/B 允许if (type == Boolean.class),但情况 1A/B、2A、5A/B 和 6A/B 会导致编译器错误?具体来说,我想在 2A 与 2B 的情况下解释这个错误,它们共享相同的类签名。
可运行的测试用例如下。提供了外部Score 和DetailedScore 类来演示涉及继承的案例,突出了案例A 和案例B 之间的区别。
ComparableTest.java
public class ComparableTest<L, T extends Comparable<? super T>> // Case A
//public class ComparableTest<L, T extends Comparable<T>> // Case B: Works when used without inheritance.
{
public static void main(String[] args)
{
new ComparableTest<String, Boolean>(new String("B"), Boolean.TRUE);
new ComparableTest<String, Float>(new String("F"), new Float(1f));
new ComparableTest<String, Score>(new String("S"), new Score(5f));
new ComparableTest<String, Score>(new String("D"), new DetailedScore<String>("DS.S", 5f));
new ComparableTest<String, DetailedScore<?>>(new String("DS"), new DetailedScore<String>("DS.DS", 5f));
}
public ComparableTest(L label, T value)
{
// Case 1A: Compiler Error: Type mismatch: cannot convert from Class<capture#2-of ? extends Comparable> to Class<T>
// Class<T> type = value.getClass(); // Q: Why can't I use Class<T>?
// Case 2A: Compiler Warning: Type safety: Unchecked cast from Class<capture#2-of ? extends Comparable> to Class<T>
// Class<T> type = (Class<T>) value.getClass(); // Case 2B: This works if 'T extends Comparable<T>' (see note in class declaration above).
// Case 3A: Compiler Warning: Comparable is a raw type. References to generic type Comparable<T> should be parameterized
Class<? extends Comparable> type = value.getClass(); // Q: Why must Comparable be a raw type here?
// Case 4A: Compiler Warning: Type safety: Unchecked cast from Class<capture#2-of ? extends Comparable> to Class<? extends Comparable<?>>
// Class<? extends Comparable<?>> type = (Class<? extends Comparable<?>>) value.getClass();
// Case 5A: Compiler Warning: Type safety: Unchecked cast from Class<capture#2-of ? extends Comparable> to Class<? extends Comparable<T>>
// Class<? extends Comparable<T>> type = (Class<? extends Comparable<T>>) value.getClass();
// Case 6A: Compiler Warning: Type safety: Unchecked cast from Class<capture#2-of ? extends Comparable> to Class<? extends Comparable<? super T>>
// Class<? extends Comparable<? super T>> type = (Class<? extends Comparable<? super T>>) value.getClass();
// Case 1A, 2A: Compiler Error: Incompatible operand types Class<T> and Class<Boolean>
// Case 2B, 3A/B, 4A/B: OK.
// Case 5A/B, 6A/B: Compiler Error: Incompatible operand types Class<capture#4-of ? extends Comparable<T>> and Class<Boolean>
if (type == Boolean.class)
{
System.out.println("Treating " + label + " as boolean (" + type.getCanonicalName() + ")");
} else if (type == Float.class) {
System.out.println("Treating " + label + " as float (" + type.getCanonicalName() + ")");
} else {
System.out.println("Treating " + label + " as (" + type.getCanonicalName() + ")");
}
return;
}
}
Score.java
public class Score implements Comparable<Score>
{
private Float value;
public Score(Float value)
{
this.value = value;
return;
}
@Override
public int compareTo(Score o)
{
return this.value.compareTo(o.value); // for brevity
}
}
DetailedScore.java
public class DetailedScore<D> extends Score
{
private D detail;
public DetailedScore(D someDetail, Float value)
{
super(value);
this.detail = someDetail;
return;
}
public D getDetail()
{
return this.detail;
}
}
【问题讨论】:
-
getClass()返回Class<?>而不是Class<T>... 但您可以放心地转换它。 -
@assylias 是的,示例中的案例 6A 转换为
Class<? extends Comparable<? super T>>;但是,在使用==运算符时,这仍然会导致编译器错误。 -
哪个编译器版本?
-
@bayou.io Oracle JDK:
Java(TM) SE Runtime Environment (build 1.7.0_55-b13),Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)在 Windows Server 2003 R2 Standard x64 上。
标签: java generics java-7 comparable