Why don't I have to import classes not used as variable types in Java?

Joe*_*oel 2 java import class

Here is an example:

import java.util.HashMap;

public class Test
{
    public static void main(String[] args)
    {
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("leorum", 1);
        map.put("ipsum", 2);
        map.put("dolor", 3);

        System.out.println(map.keySet().toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

Everything compiles and runs fine. However, when I move map.keySet() to another variable:

import java.util.HashMap;

public class Test
{
    public static void main(String[] args)
    {
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("leorum", 1);
        map.put("ipsum", 2);
        map.put("dolor", 3);

        Set<String> keys = map.keySet();
        System.out.println(keys.toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

I get an error thrown at me:

Exception in thread "main" java.lang.Error: Unresolved compilation problem:
    Set cannot be resolved to a type
    at Test.main(Test.java:12)
Run Code Online (Sandbox Code Playgroud)

我理解为什么第二个例子出现错误,但为什么我第一个没有错误呢?如果map.keySet()不导入java.util.Set ,java编译器如何知道返回什么?

我也在其他编程语言中看到过这种行为,特别是C++.

Jon*_*eet 5

我理解为什么第二个例子出现错误,但为什么我第一个没有错误呢?如果map.keySet()没有导入,java编译器如何知道返回的内容java.util.Set

它知道这两种方式 - 它是字节码中元数据的一部分.

它不知道的是你的意思Set<String>.导入只会更改源代码中名称的含义 - 并且该名称不会出现在第一段代码的源代码中.

JLS第7.5节开始:

导入声明允许通过由单个标识符组成的简单名称(第6.2节)引用命名类型或静态成员.

您没有在第一个示例中引用简单名称,因此上述优点无关紧要.

换句话说,导入只允许这一行(在第二个样本中有效):

java.util.Set<String> keys = map.keySet();
Run Code Online (Sandbox Code Playgroud)

写成:

Set<String> keys = map.keySet();
Run Code Online (Sandbox Code Playgroud)

就是这样.