为什么Java编译器会抱怨显式导入名称冲突而不是导入包.*?

mer*_*011 7 java

以下代码编译并正确运行.

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我import java.util.*;改为import java.util.Scanner;,我将得到以下编译器错误.

Foo.java:1: error: Scanner is already defined in this compilation unit
Run Code Online (Sandbox Code Playgroud)

似乎在这两种情况下,编译器应该能够同样消除歧义,那么为什么它只在第二种情况下抱怨呢?

Rog*_*gue 5

这将发生,因为您已经有一个名为Scanner的本地类.您需要使用其完全限定名称来调用它:

java.util.Scanner scan = new java.util.Scanner(System.in);
Run Code Online (Sandbox Code Playgroud)

另外,创建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());
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么会这样

一个import简单的告诉编译器到哪里寻找在编译时的符号.我不记得头顶的阶段(预处理/编译),但包导入不是那些类成员的显式声明.通过说import foo.bar.*,你说"在编译时在这个包目录中查找符号",而是import foo.bar.Scanner说"将Scanner符号指向此".

简而言之,特定的导入显然是您有"扫描仪"的符号,而包导入不指定与符号的这种特定关系.