我有一个关于类型参数的基本问题,这是我在解决问题时遇到的.
我有一个字符串数组的类,我使用自定义Comparator类进行排序.下面是我的Comparator课程
class SortComparator implements Comparator<String>
{
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return o1.compareTo(o2);
}
}
Run Code Online (Sandbox Code Playgroud)
上面的类运行正常并输出所需的结果.
如果类名更改SortComparator为SortComparator<String>compare方法则需要更改.更改后的类看起来像这样
class SortComparator<String> implements Comparator<String>
{
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return ((java.lang.String) o1).compareTo((java.lang.String) o2);
}
}
Run Code Online (Sandbox Code Playgroud)
上面的类也运行良好并输出所需的结果
为什么有需要显式转换String对象o1,并o2到java.lang.String时候他们已经是同一类的对象?
我在网上搜索了一段时间的查询,发现了一个非常相似的问题
将两个Integers与我自己的Comparator进行比较
这个问题的答案说是因为shadowing.
我知道局部变量,实例变量和类变量方面的阴影,但在这种情况下它是如何工作的?
问题在于调用泛型类型String.它是泛型类型参数和实际类之间的冲突String.
因为类型参数String是无界的,所以Java编译器替换它,Object因此方法的参数compare起作用,Object而对象类没有compareTo方法因此你必须强制转换.
尝试以下示例工作正常.
class SortComparator<T> implements Comparator<String>
{
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return o1.compareTo(o2);
}
}
Run Code Online (Sandbox Code Playgroud)
请查看有关Erasure of Generic Types的 Java文档
在类型擦除过程中,Java编译器将擦除所有类型参数,并在类型参数有界时将其替换为第一个绑定,如果类型参数为无界,则替换为Object.
下面的示例直接从上面的Java文档中复制,以便更清晰.
考虑以下表示单链表中节点的泛型类:
public class Node<T> {
private T data;
private Node<T> next;
public Node(T data, Node<T> next) }
this.data = data;
this.next = next;
}
public T getData() { return data; }
// ...
}
Run Code Online (Sandbox Code Playgroud)
因为类型参数T是无界的,所以Java编译器将其替换为Object:
public class Node {
private Object data;
private Node next;
public Node(Object data, Node next) {
this.data = data;
this.next = next;
}
public Object getData() { return data; }
// ...
}
Run Code Online (Sandbox Code Playgroud)