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.