以下代码编译并正确运行。
import java.util.*;
import java.io.*;
class Scanner {
public Scanner(InputStream in) {
}
}
public class Foo{
public static void main(String[] args) {
java.util.Scanner in = new java.util.Scanner(System.in);
System.out.println(in.getClass());
Scanner in2 = new Scanner(System.in);
System.out.println(in2.getClass());
}
}
但是,如果我将import java.util.*;
更改为import java.util.Scanner;
,我将收到以下编译错误。
Foo.java:1: error: Scanner is already defined in this compilation unit
似乎在这两种情况下,编译器都应该能够同样消除歧义,那么为什么它只会在第二种情况下抱怨?
答案 0 :(得分:5)
这将发生,因为您已经有一个名为Scanner的本地类。您需要使用其完全限定名称来调用它:
java.util.Scanner scan = new java.util.Scanner(System.in);
此外,将Scanner
设为嵌套静态类:
public class Foo {
private static class Scanner {
public Scanner(InputStream in) {
}
}
public static void main(String[] args) {
java.util.Scanner in = new java.util.Scanner(System.in);
System.out.println(in.getClass());
Scanner in2 = new Scanner(System.in);
System.out.println(in2.getClass());
}
}
import
只是告诉编译器在编译时在哪里查找符号。我不记得我头顶的阶段(预处理/编译),但包导入不是这些类成员的显式声明。通过说import foo.bar.*
,你说"在编译"时在这个包目录中查找符号,而import foo.bar.Scanner
说"点Scanner
符号到这个&# 34。
简而言之,一个特定的导入显然是你有#34; Scanner"的符号,而包导入没有指定这个特定的符号关系。
答案 1 :(得分:2)
为什么导入java.util.*
不会出错?
它不会引发错误,因为没有关于“java.util.Scanner
”类和您的班级Scanner
的混淆。
当您将导入用作java.util.Scanner
时,它会与Scanner
中的util
与您的班级名称冲突。
这就是出错的原因。
答案 2 :(得分:0)
单一类型导入声明与顶级类型声明的冲突在JSL §7.5.1. Single-Type-Import Declarations中描述:
引用的一个例子如果单一类型导入声明导入其简单名称的类型 是n,编译单元也声明了顶级类型(§7.6) 其简单名称为n,发生编译时错误。
import java.util.Vector;
class Vector { Object[] vec; }
由于Vector的重复声明,导致编译时错误。
答案 3 :(得分:0)
当您的java类名和导入库名相同时,会发生这种情况。在您的情况下,Scanner是指类名而不是库。将类名更改为其他名称将是解决错误的最简单方法。