♦ A package in Java is used to group related classes. Think of it as a folder in a file directory. ♦ When developing a Java program, you put classes that go together in the same package. ♦ We also use packages to avoid name conflicts. ♦ Every class belongs to a package. ♦ If we do not explicitly declare a class in a package, the class belongs to the default package. ♦ The default package contains every Java class in the current folder that does not use the package keyword. ♦ To declare that the class (eg Person) belongs to the pfaff package, write before any command: package pfaff;
public class Person { ... }
♦ Java naming convention recommends package names be all lowercase, unless an acronym is part of thename. For example pfaff myBytecode etc. |
♦ One of the advantages of using packages is that, with proper compilation, the bytecodes of the classes belonging to the pfaff package will be stored in the same folder, which will be called pfaff. ♦ For this to happen, the compilation of the class should be done with the -d parameter: C:\Users\alex>javac -d shop Person.java ↻
♦ shop is an arbitrary folder under which pfaff folder will be created, containing the Person.class file.Fig.1 shop will be created under the current folder |
♦ shop can be any folder in some corner of your disk or network, where you have the privilege to create folders and save files. Can be, for example, C:\factory C:\Users\alex>javac -d C:\factory Person.java ↻
Fig.2 C:\factory will be created if it does not exist |
♦ We can write the name of a package using dots (.) as in the following example package europe.france.pfaff;
public class Person { ... }
♦ Compiling this class into C:\factory will create a series of folders, as shown in Fig.3C:\Users\alex>javac -d C:\factory Person.java ↻
Fig.3 the application classes. Some classes will be included in package (folder) europe, others in package europe.france and others in europe.france.pfaff |
♦ Another advantage of using packages is that they create a namespace, under which all its classes are known. So Person class is now known as pfaff.Person and cann't be confused with whichever Person class belonging to other packages or even in the default package. ♦ The package name is prefixed to the name of the class, separated by the dot operator. pfaff.Person
♦ Inside the pfaff package you can refer to this class without prefixing the package name. Just Person
|
♦ Suppose Person class is in the pfaff package .. package pfaff;
public class Person {}
♦ .. and the Main class is in the same package. package pfaff; public class Main {
public static void main (String [] args) {
Person john;
}
}class by writing only its name (without prefixing the package name). |
♦ Suppose Person class is in the pfaff package .. package pfaff;
public class Person {}
♦ .. and Main class is in another package (bosch) package bosch; public class Main {
public static void main (String [] args) {
pfaff.Person john;
}
}refer to the Person class by prefixing its package name. |
♦ When working with classes from different packages, there is also another way to use a foreign class. The import keyword. package pfaff;
public class Person {}
♦ The Main class is in different package (bosch) and uses the import keyword package bosch;
♦ Because Main class uses the import keyword, we can refer to the Personimport pfaff.Person; public class Main {
public static void main (String [] args) {
Person john;
}
}class without prefixing its package name. ♦ When we use many classes from a foreign package, the import keyword can also be written as: package bosch;
import pfaff.*; public class Main {
public static void main (String [] args) {
Person john;
}
} |
☕ | A class file can contain any number of import statements. The import statements must appear after the package statement and before the class declaration. |
☕ | You never need to use import statements, because you can always refer to a class by its fully qualified name (the name of the class prefixed with its package name). The import keyword is strictly a convenience. In fact, when compiling your classes, the compiler removes all import statements and replaces all class names with their fully qualified name. That said, you will use import statements all the time. Using the fully qualified name for every class is tedious and can actually make your code more difficult to read. |
☕ | There is no size or performance benefit gained from importing classes individually versus importing an entire package. The compiled bytecode will look exactly the same. |
♦ Let's compile the absolutely empty (for simplicity) Person class
package pfaff;
public class Person {}
C:\Users\alex>javac -d C:\factory Person.java ↻
♦ Compilation was successful. The bytecode Person.classcreated inside C:\factory\pfaff folder. So far so good ♦ Now let's compile the almost empty (for simplicity) Main.java program, which uses a little bit of Person class
package bosch; public class Main {
public static void main (String [] args) {
pfaff.Person john; // a simple reference to Person class
}
}C:\Users\alex>javac -d C:\factory Main.java ↻
.. compilation error: package pfaff does not exist ..
♦ Compilation failed! Why?♦ The compiler (thanks to -d parameter and the package declaration) knows where to save the bytecode (C:\factory\bosch) ♦ The problem is that, trying to resolve the unknown pfaff.Person symbol, it doesn't know where to look for this class. ♦ We know that pfaff.Person class is under C:\factory folder, but the compiler doesn't know that. ♦ You see, it's another matter where the bytecode is stored after a successful compilation, and another matter where the involved classes are located. |
♦ Here comes the CLASSPATH environment variable. It is a variable from which the compiler is informed where the involved classes may be hiding. ♦ It is your responsibility to give the appropriate value(s) to this variable. ♦ You have to append to the existing value(s) the C:\factory folder. ♦ First check if this variable already exists and has the appropriate value(s): C:\Users\alex>echo %CLASSPATH% ↻
♦ If CLASSPATH is not set or is set but doesn't include the C:\factory folder,then do the following that is not a permanent solution, because lasts as long as you are inside the command line: ♦ if CLASSPATH is not set C:\Users\alex>set CLASSPATH=C:\factory ↻
♦ or, if CLASSPATH is already set C:\Users\alex>set CLASSPATH=%CLASSPATH%;C:\factory ↻
♦ For a permanent solution you have to edit the System Environment Variables. |
☕ | Why have we not had to use CLASSPATH until now? Because in all of the examples up until now, all of the bytecode needed has been in the same folder, and if no CLASSPATH environment variable is found, the compiler and JRE look in the current folder. |
☕ | CLASSPATH contains the names of all folders and JAR files, where the necessary bytecode can be found. A collection of bytecode files can be compressed into a single file known as a Java Archive (JAR). If the bytecode you need is in a JAR file, the JAR file name needs to appear in the CLASSPATH environment variable. |
♦ After setting the CLASSPATH variable, let's try to compile again the Main.java program: C:\Users\alex>javac -d C:\factory Main.java ↻
♦ This time the compilation was successfull, bytecode Main.class created inside C:\factory\bosch folder.♦ Now the long-awaited moment has arrived to run our program. C:\Users\alex>java Main ↻
Error: Could not find .. Main class ..
♦ Unfortunately Main doesn't run! The reason is not a CLASSPATH problem, because we havealready set the CLASSPATH environment variable to include C:\factory, which is the correct folder. The reason the Main class cannot run is that we are using the wrong name. The Main class is in the bosch package, so from now on the name of the class is bosch.Main C:\Users\alex>java bosch.Main ↻
♦ Finally, the program is running (you saw nothing because of its extreme simplicity) |
♦ There are built-in packages (packages from the Java API) and user-defined packages (created by us). ♦ A Java package is a library of prewritten classes, included in the JDK. |