bruceeckel.util;
Now this package name can be used as an umbrella name space for the following two files: 2 ftp://ftp.internic.net
168
Thinking in Java
www.BruceEckel.com
//: Vector.java
// Creating a package
package com.bruceeckel.util;
public class Vector {
public Vector() {
System.out.println(
"com.bruceeckel.util.Vector");
}
} ///:~
When you create your own packages, you’ll discover that the package statement must be the first non-comment code in the file. The second file looks much the same:
//: List.java
// Creating a package
package com.bruceeckel.util;
public class List {
public List() {
System.out.println(
"com.bruceeckel.util.List");
}
} ///:~
Both of these files are placed in the subdirectory on my system:
C:\DOC\JavaT\com\bruceeckel\util
If you walk back through this, you can see the package name com.bruceeckel.util, but what about the first portion of the path? That’s taken care of in the CLASSPATH
environment variable, which is, on my machine:
CLASSPATH=.;D:\JAVA\LIB;C:\DOC\JavaT
You can see that the CLASSPATH can contain a number of alternative search paths. There’s a variation when using JAR files, however. You must put the name of the JAR file in the classpath, not just the path where it’s located. So for a JAR named grape.jar your classpath would include:
CLASSPATH=.;D:\JAVA\LIB;C:\flavors\grape.jar
Once the classpath is set up properly, the following file can be placed in any directory: (See page 94 if you have trouble executing this program.):
//: LibTest.java
// Uses the library
package c05;
import com.bruceeckel.util.*;
public class LibTest {
public static void main(String[] args) {
Vector v = new Vector();
List l = new List();
}
} ///:~
Chapter 5: Hiding the Implementation
169
When the compiler encounters the import statement, it begins searching at the directories specified by CLASSPATH, looking for subdirectory com\bruceeckel\util, then seeking the compiled files of the appropriate names (Vector.class for Vector and List.class for List). Note that both the classes and the desired methods in Vector and List must be public.
Automatic compilation
The first time you create an object of an imported class (or you access a static member of a class), the compiler will hunt for the .class file of the same name (so if you’re creating an object of class X, it looks for X.class) in the appropriate directory. If it finds only X.class, that’s what it must use. However, if it also finds an X.java in the same directory, the compiler will compare the date stamp on the two files, and if X.java is more recent than X.class, it will automatically recompile X . java to generate an up-to-date X.class.
If a class is not in a .java file of the same name as that class, this behavior will not occur for that class.
Collisions
What happens if two libraries are imported via * and they include the same names? For example, suppose a program does this:
import com.bruceeckel.util.*;
import java.util.*;
Since java.util.* also contains a Vector class, this causes a potential collision. However, as long as the collision doesn’t actually occur, everything is OK – this is good because otherwise you might end up doing a lot of typing to prevent collisions that would never happen.
The collision does occur if you now try to make a Vector:
Vector v = new Vector();
Which Vector class does this refer to? The compiler can’t know, and the reader can’t know either. So the compiler complains and forces you to be explicit. If I want the standard Java Vector, for example, I must say:
java.util.Vector v = new java.util.Vector();
Since this (along with the CLASSPATH) completely specifies the location of that Vector, there’s no need for the import java.util.* statement unless I’m using something else from java.util.
A custom tool library
With this knowledge, you can now create your own libraries of tools to reduce or eliminate duplicate code. Consider, for example, creating an alias for System.out.println( ) to reduce typing. This can be part of a package called tools:
//: P.java
// The P.rint & P.rintln shorthand
package com.bruceeckel.tools;
public class P {
public static void rint(Object obj) {
170
Thinking in Java
www.BruceEckel.com
System.out.print(obj);
}
public static void rint(String s) {
System.out.print(s);
}
public static void rint(char[] s) {
System.out.print(s);
}
public static void rint(char c) {
System.out.print(c);
}
public static void rint(int i) {
System.out.print(i);
}
public static void rint(long l) {
System.out.print(l);
}
public static void rint(float f) {
System.out.print(f);
}
public static void rint(double d) {
System.out.print(d);
}
public static void rint(boolean b) {
System.out.print(b);
}
public static void rintln() {
System.out.println();
}
public static void rintln(Object obj) {
|