让我感到困惑的一个例子:
Thing.java:
import java.util.Date;
class Thing {
static Date getDate() {return new Date();}
}
(相同包)TestUsesThing.java:
// not importing Date here.
public class TestUsesThing {
public static void main(String[] args) {
System.out.println(Thing.getDate().getTime()); // okay
// Date date = new Date(); // naturally this wouldn't be okay
}
}
为什么没有必要导入Date才能在其中一个上调用getTime()?
答案 0 :(得分:25)
只需要在Java中导入,因此编译器知道键入
时Date
是什么
Date date = new Date();
导入与C / C ++中的#include
不同;类路径上的所有类型都是可用的,但是你import
它们只是为了不必编写完全限定的名称。在这种情况下,这是不必要的。
答案 1 :(得分:1)
好问题!!
我认为结果是java编译器处理表达式与语句之间的区别。
Date d = new Date(); // a statement
其中
new Thing().getDate().getTime()
是在println方法调用中发生的表达式。当您在新Thing()上调用getDate时,编译器会尝试通过查看Thing类的类型信息来处理表达式,这是获取Date类型声明的地方。 但是当你尝试在像
这样的语句中单独使用Date时Date d = new Thing().getDate();
您要将结果分配给当前作用域中的类型(类TestUsesThing),编译器会尝试解析该作用域内的类型。因此,您会看到未知类型的编译器错误。
答案 2 :(得分:0)
Thing和TestUsesThing在同一个包中吗?如果是这样,那么你不必导入东西。您必须导入日期的原因是因为它位于不同的包中。
答案 3 :(得分:0)
import
语句用于几件事。
每当我们说
System.out.println( new Thing().getDate().getTime() )
编译器从左到右解析此语句并进入该类。
第一级编译器解析。
作为消费者,TestUsesThing只获取长变量。
System.out.println( new Thing().getDate() )
5.1在这种情况下,我们隐式访问.toString()方法
答案 4 :(得分:0)
实际上,这是一个理想的例子,因为两个不同的标准Java Date类: java.util.Date 和 java。 sql < /em>.Date
它如何知道使用哪一个?简单。 getDate()方法被声明为Thing类定义的一部分,该声明的一部分是其返回类型:
public java.util.Date getDate() {
return this.date;
}
当然,如果你在Thing类的定义中有一个导入 - 并且它没有含糊不清,你只需说:
public Date getDate() {
如果你要解码Thing类的二进制文件,你会看到getDate方法的方法签名,它包含返回类型的完全限定类名(包括包)。
导入只是告诉编译器在引用没有明确限定条件的类时要采用的包。只要看到不合格的类名,就会扫描导入列表,并搜索包。如果没有歧义(例如同时导入java.util.date和java.sql.Date),将使用该类。如果您可以隐式确定类,或者类名是完全限定的,则无需导入。