Something that\'s confused me - an example:
Thing.java:
import java.util.Date;
class Thing {
static Date getDate() {return new Date();}
}
Importing in Java is only necessary so the compiler knows what a Date
is if you type
Date date = new Date();
Importing is not like #include
in C/C++; all types on the classpath are available, but you import
them just to keep from having to write the fully qualified name. And in this case, it's unnecessary.
Are Thing and TestUsesThing in the same package? If so then you don't have to import Thing. The reason you have to import Date is because it's in a different package.
Good question !!
I think the result is the difference between how java compiler handles expressions vs statements.
Date d = new Date(); // a statement
where as
new Thing().getDate().getTime()
is an expression as it occurs inside println method call. When you call getDate on new Thing() the compiler tries to handle the expression by looking at the type info for Thing class, which is where it gets the declaration of type Date. But when you try to use Date separately in a statement like
Date d = new Thing().getDate();
you are assigning the result to a type in the current scope (class TestUsesThing ), compiler tries to resolve the type within that scope. As a result, you see the compiler error for unknown type.
import
statements are used for couple of things.
Whenever we say
System.out.println( new Thing().getDate().getTime() )
The compiler parses this statement left to right and gets into that class.
First level compiler parsing.
As a consumer TestUsesThing gets only long variable.
System.out.println( new Thing().getDate() )
5.1 In this case we are implicitly accessing .toString() method
Actually, that was an ideal example, since there's two different standard Java Date classes: java.util.Date and java.sql.Date.
How does it know which one to use? Simple. The getDate() method is declared as part of the definition of the Thing class, and part of that declaration is its returntype:
public java.util.Date getDate() {
return this.date;
}
Of course, if you have an import in the definition of the Thing class - and it's not ambiguous, you simply say:
public Date getDate() {
If you were to decode the binary of the Thing class, you'd see the method signature of the getDate method, and it includes the fully-qualified class name (including package) of the return type.
An import is simply a way of telling the compiler what package(s) you want to assume when referring to classes without explicit qualifications. The list of imports will be scanned whenever an unqualified class name is seen, and the packages will be searched. If there's no ambiguity (such as importing both java.util.date and java.sql.Date), that class will be used. If you can determine the class implicitly, or if the class name is fully qualified, you don't need to import.