tags:

views:

345

answers:

5

Something that's confused me - an example:

Thing.java:

import java.util.Date; 

class Thing { 
    static Date getDate() {return new Date();}
}

(same package) 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
    }

}

Why is it not necessary to import Date to be able to call getTime() on one of them?

+22  A: 

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.

Michael Myers
Aha that makes complete sense, thank you!
jjujuma
+1: I'm learning Java myself and of all the material I've read, I don't recall seeing that tidbit of information explained that way. That clears up alot. Thanks.
Arnold Spence
The other somewhat related comment is that all of the java.lang package is automatically imported. So that means that you can use things like System without an import statement.
Jay R.
+1  A: 

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.

Amit
A: 

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.

mamboking
Yes, sorry, the question was indeed about the Date import, not the relationship between the classes which I have clarified now.
jjujuma
A: 

import statements are used for couple of things.

  1. Compiler type checking and avoid naming collision.
  2. Ensures byte code linkage

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.

  1. Go to thing class
  2. #compile doesn't have any linkage or ClassVersion error from Thing.class
  3. Check Thing.class has getDate method.
  4. if #3 is good then compiler pointer is still in Thing.class (which has date import statements) and I could invoke Time method.
  5. 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

A: 

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.

Tim H