[英]Why don't I have to import classes not used as variable types in Java?
这是一个例子:
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());
}
}
一切都编译好,运行良好。 但是,当我将map.keySet()
移动到另一个变量时:
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());
}
}
我收到一个错误:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Set cannot be resolved to a type
at Test.main(Test.java:12)
我理解为什么第二个例子出现错误,但为什么我第一个没有错误呢? java编译器如何知道map.keySet()
返回而不导入java.util.Set?
我也在其他编程语言中看到过这种行为,特别是C ++。
我理解为什么第二个例子出现错误,但为什么我第一个没有错误呢? java编译器如何知道
map.keySet()
返回而不导入java.util.Set
?
它知道这两种方式 - 它是字节码中元数据的一部分。
它不知道的是Set<String>
。 导入只会更改源代码中名称的含义 - 并且该名称不会出现在第一段代码的源代码中。
从JLS第7.5节开始 :
导入声明允许通过由单个标识符组成的简单名称(第6.2节)引用命名类型或静态成员。
您没有在第一个示例中引用简单名称,因此上述优点无关紧要。
换句话说,导入只允许这一行(在第二个样本中有效):
java.util.Set<String> keys = map.keySet();
写成:
Set<String> keys = map.keySet();
就是这样。
import
指令是一种纯粹的语法特性,它允许您引用类型而不用包名限定它。
由于您的第一个代码从不引用Set
类型,因此无需导入即可正常工作。
import
与使用类无关; 它只影响你如何写出它的名字。
java编译器知道map.keySet()
返回什么,因为它在HashMap
的定义中。
public Set<K> keySet() { ... }
编译HashMap时,编译器知道什么是Set<>
因为在HashMap的源代码中有一个import
语句(或者更确切地说,在这种情况下,不需要import语句,因为Set与HashMap在同一个包中)。
然后编译器将此信息放在已编译的类文件中,作为方法“签名”的返回类型。
当您使用map.keySet()
,您不必指定方法的返回类型,因为编译器可以访问HashMap的类文件,因此它知道它需要的所有内容。
因为在第一个示例中,keySet()在HashMap对象中执行,而不是在您的main中执行,这就是您不需要声明它的原因。
在第一种情况下, map.keySet()
的类型是已知的。 返回类型是方法合同的一部分。
在第二种情况下,非限定名称Set
不足以识别变量keys
的类型。 完全限定的类型名称不是从作业的右侧推断出来的。 您可以完全限定名称,也可以导入名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.