这是“ Java中的数据结构和算法(第六版)”一书中的代码片段
这是用于克隆SinglyLinkedList
实现的示例方法。
为了更好地理解,我在Eclipse中进行了编码。
我有两个问题:
首先,在第3行中,我收到以下警告:键入安全性:“未经检查从对象到SinglyLinkedList<E>
的转换”。为什么会这样?
第二,在第5行中,为什么我们有“ new Node<>(
...”,为什么不使用“ new Node<E>(
...”
两者有什么区别?
public SinglyLinkedList<E> clone( ) throws CloneNotSupportedException {
//always use inherited Object.clone() to create the initial copy
SinglyLinkedList<E> other = (SinglyLinkedList<E>) super.clone( ); //<---LINE 3 safecast
if (size > 0) { // we need independent chain of nodes
other.head = new Node<>(head.getElement( ), null);//<---LINE 5
Node<E> walk = head.getNext( ); // walk through remainder of original list
Node<E> otherTail = other.head; // remember most recently created node
while (walk != null) { // make a new node storing same element
Node<E> newest = new Node<>(walk.getElement( ), null);
otherTail.setNext(newest); // link previous node to this one
otherTail = newest;
walk = walk.getNext( );
}
}
return other;
}
答案 0 :(得分:3)
首先,在第3行中,我收到以下警告:键入安全性:“未经检查从对象到SinglyLinkedList的转换”。为什么会这样?
方法clone()
返回一个Object
,因此您必须将其强制转换为SinglyLinkedList
,编译器不能保证这样的Object
将是SinglyLinkedList
,所以你会得到警告。
我建议阅读有关Generics
如果要隐藏该警告,可以使用以下注释
@SuppressWarnings("unchecked")
public SinglyLinkedList<E> clone( ) throws CloneNotSupportedException {
第二行,为什么我们有“ new Node <>(...”,为什么不使用“ new Node(...”)呢?两者之间有什么区别?
由于Java7,由于以下原因,在调用构造函数时无需声明泛型类型
Type Inference for Generic Instance Creation。
如果您编写了= new Node(head.getElement( ), null);
,那么您将创建一个原始类型而失去了泛型的优势。您也会得到警告。
JLS - Raw Type声明:
仅允许出于对遗留代码兼容性的考虑而使用原始类型。强烈反对在Java编程语言引入泛型之后编写的代码中原始类型的使用。 Java编程语言的未来版本可能会禁止使用原始类型。
答案 1 :(得分:1)
第3行:
您正在将super.clone()
转换为SinglyLinkedList<E>
的对象。该警告只是希望您检查super.clone()
是否真的是SinglyLinkedList<E>
的实例。您可以通过简单的选择来做到这一点:
if (super.clone() instanceof SinglyLinkedList<E>)
SinglyLinkedList<E> other = (SinglyLinkedList<E>) super.clone();
第5行:
那么您可以使用new Node <E>
代替new Node<>
。没有区别。简单地说,编译器已经知道您将实例化的泛型类型,因此使用new Node <E>
完全是多余的。我不确定,但是我认为您必须在Java的早期版本(我认为Java 6及更低版本)中使用new Node <E>
。
答案 2 :(得分:1)
1)clone
方法很需要返回Object
see here,因此任何类型的转换都不安全
2)other.head
已经是<E>
,因此您不必将<E>
添加到新的变量中,编译器已经知道泛型的类型。