我对Java比较新,所以问题就在于此。为什么Java转换对象以及在转换对象时编译器究竟发生了什么。这是我的简单级别订单搜索代码。
void LevelOrder(Node root)
{
Queue<Node> Q = new LinkedList();
Q.add(root);
while(!Q.isEmpty()){
Node p = Q.poll();
System.out.print(p.data+ " ");
if(p.left != null) Q.add(p.left);
if(p.right != null) Q.add(p.right);
}
}
当我在黑客级别提供的基于Web的IDE上运行此代码时,它会编译,但会给我以下警告。
Note: Solution.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
当我通过将poll
的行更改为
Node p = (Node)Q.poll();
它仍然编译显示相同的警告。
然而,在我的IntelliJ IDE上,第一个代码甚至不会编译,只有第二个代码(使用显式强制转换)编译。
有人可以解释这里发生了什么。 除了解决错误之外,有人可以解释为什么一个编译器允许这行编译,而另一个编译器没有显式转换。
Node p = Q.poll();
答案 0 :(得分:3)
new LinkedList();
这是一个raw-typed集合 - 编译器不知道其中包含哪些类型的元素(即使其中实际上没有没有)。
因此,当您尝试将其分配给只能包含Node
类型元素的引用时:
Queue<Node> Q = new LinkedList();
然后编译器无法知道这是否安全。
修复很简单:告诉编译器元素的类型:
Queue<Node> Q = new LinkedList<Node>();
在Java 7 +中可以更简单:
Queue<Node> Q = new LinkedList<>();
在这种情况下,编译器将类型推断为<Node>
。 <>
被称为&#34;钻石符号&#34 ;;它不能在所有情况下使用,但可以在这样的赋值上下文中使用。
答案 1 :(得分:1)
原因是这一行:
Queue<Node> Q = new LinkedList();
如果您将其更改为
Queue<Node> Q = new LinkedList<Node>();
警告消遣者。
在第一种情况下,您有一个Object
列表,
在第二个Node
列表中。
这在编译时主要是相关的。稍后在执行期间,所有集合都是Object类型。如果将其他类型的对象输入到列表中,则会在运行时获得ClassCastException。 (如果编译器无法检测到您添加了错误类型的对象)
从java 1.7开始,只需编写
即可Queue<Node> Q = new LinkedList<>();
编译器现在足够聪明,知道你的意思是Node
。
答案 2 :(得分:1)
在声明如下链接列表后添加<>
修复此行:
Queue<Node> Q = new LinkedList<>();
或者你也可以这样做:
Queue<Node> Q = new LinkedList<Node>();
请注意,可以使用JDK 7中的菱形运算符代替显式类型参数。所以我更喜欢第一种方式。