Grouping classes together
Large Java projects have a lot of classes. It's difficult to manage them if they are stored in the same directory. Packages provide a mechanism to group classes together into the same module (package). A package can contain others packages inside. It's like directories in a file system.
In general, packages give us the following advantages:
- to group related classes together that makes easier to figure out where a certain class you are looking for is;
- to avoid the conflict of class names;
- to control access to classes and members together with access modifiers (it's considered in another topic).
According to the naming convention, packages are always written in lowercase, for example:
model
collection
utils
Here is an example project with a simple packages and classes tree.
An example of multi-packages project structure
Here is a directory "src" at the top of the tree. This is the source root directory. In this tree, the full name of the class User is org.company.webapp.data.User.
You can output this using the following code:
System.out.println(User.class.getName()); // org.company.webapp.data.User
Classes declared inside a package has a special keyword package at the top of the file.
package org.company.webapp.data;
public class User {
}
Avoiding the conflict of class names
When you use external libraries the situation is possible that two classes have the same name. Packages allow avoiding the conflict of class names because the full class name includes names of packages. Also, it's needed to avoid the conflict between names of packages.
To avoid creating packages with the same names as other public packages it is recommended that you start your package hierarchy with the reverse domain name of your company (or another organization). For example:
org.company
org.hyperskill
net.labs
Importing classes
If two classes are located in the same package there is no problem to use one class inside another. If one of these classes is located in another package, to use one class inside another you should write an import statement using the keyword import.
Here is an example. We have two public classes in different packages:
org.hyperskill.java.packages.theory.p1.A
org.hyperskill.java.packages.theory.p2.B
To use the class B inside the class A we should make an import statement.
package org.hyperskill.java.packages.theory.p1; // current package
import org.hyperskill.java.packages.theory.p2.B; // it's required to make the import
public class A {
public static void method() {
B b = new B();
}
}
Also, it's possible to import all classes from the package, using "*" instead of a particular class name.
import org.hyperskill.java.packages.theory.p3.*; // import all classes from the package
Importing standard classes
import java.util.Scanner;
Specifying the full class name instead of importing
java.util.Scanner scanner = new java.util.Scanner(System.in);
java.util.Date now = new java.util.Date();
Static imports
package org.hyperskill.java.packages.theory;
import static java.util.Arrays.*; // instead of the statement "import java.util.Arrays;"
public class Main {
public static void main(String[] args) {
int[] numbers = { 10, 4, 5, 47, 5, 12 }; // an array
sort(numbers); // instead of writing Arrays.sort(...)
int[] copy = copyOf(numbers, numbers.length); // instead of writing Arrays.copyOf(...)
}
}