Packages in Java
A Java package is a collection of similar types of sub-packages, interfaces, and classes. In Java, there are two types of packages: built-in packages and user-defined packages. The package keyword is used in Java to create Java packages.
Introduction to Packages in Java
Let’s find out why we even need packages in the first place. Say you have a laptop and a bunch of data you want to store. Data includes your favorite movies, songs, and images.
So, do you store them all in a single folder or make a separate category for each one and store them in their corresponding folder?
It is obvious that anyone would like to create separate folders for images, videos, songs, movies, etc. And the reason is the ease of accessibility and manageability.
How does Packages in Java improve accessibility and manageability?
If you had clustered everything inside a single folder, you would probably spend a lot of time finding the correct file. But, separating your files and storing them in the correct folder saves you a lot of time.
This way, we’re improving accessibility. Accessibility and manageability go kind of hand in hand. Managing a file is related to how easy it’s to modify a specified file to incorporate future needs.
Though management includes other factors as well, like how well the code is written, having those files in a structured format is an essential requirement.
You can think of it like that – “What if we write this article in a not-so-structured format and combine everything inside a single paragraph?” You obviously will have a hard time reading it. Isn’t it?
So using the same analogy in application development, but here, packages in Java provide little more than that. In simple words, packages in Java are nothing but a folder that contains related files.
These files could be of type Java classes or interfaces or even sub-packages (don’t forget the storing data inside the laptop analogy).
Types of Packages in Java
Packages in Java can be categorised into 2 categories.
- Built-in / predefined packages
- User-defined packages.
Let’s understand them in a little more detail.
When we install Java on a personal computer or laptop, many packages are automatically installed. Each of these packages is unique and capable of handling various tasks. This eliminates the need to build everything from scratch. Here are some examples of built-in packages:
Let’s see how you can use an inbuilt package in your Java file.
- In this example, we import java.lang.* to have access to some of the fundamental classes provided by Java, such as Math, String, and Integer.
- The code demonstrates the usage of these classes by calculating the area of a circle, determining the length of a string, and converting an integer to its binary representation.
User-defined packages are those that developers create to incorporate different needs of applications. In simple terms, User-defined packages are those that the users define. Inside a package, you can have Java files like classes, interfaces, and a package as well (called a sub-package).
A package defined inside a package is called a sub-package. It’s used to make the structure of the package more generic. It lets users arrange their Java files into their corresponding packages. For example, say, you have a package named cars. You’ve defined supporting Java files inside it.
But now you want to define another package called superCars. Should we define it inside the car's package or outside as another package? At this point, you must say that it should go inside cars because superCars are also related to cars.
But to be more generic, we’re defining it as a separate package, but having it inside cars makes them part of cars.
Let’s look over the package's structure using an example.
We’ve defined four packages, and some of them even have sub-packages defined inside them. We distributed Java files to each package. By this example, you can calculate the importance of giving a good name to files and placing them inside a designated package. The Sooner the application grows, the more the importance of packages and this structured format becomes prominent.
Create, Compile and Run a Java Package Program
Use package keyword to create a package in Java
Let’s understand the code snippet. We’ve defined a package named myFirstPackage. After that, we’ve made a class called Main, and since this is a public class, we must save this file with the same name as the class i.e. Main.java.
After compilation, when we execute this program, it’ll print us the output. (Hop over to the next point to know how to compile and execute your program)
A constraint that we must follow – Sequence of the program must start from declaring the package, then single or multiple import lines and at last class definitions.
Compile a Java Package
To compile the Java package, open the command prompt and run the following command
-d switch is used to define the destination folder to keep the generated Java class file. To use the current directory as a destination folder, use (dot) in place of the destination directory path with the name.
Run a Java File using Package Name
To run a Java package program:
After compiling (or performing step number (b)), use the below command to run your first Java package program.
Accessibility of Packages in Java
As you may know, in Java, we do everything inside classes. So, limiting access to variables and methods by different files must be handled for security purposes. We mainly focus on package-level accessibility here, but you can check out the table below to know more.
Note: Java has four modifiers: public, protected, private, and default.
Except for private members of a class, all other members can be accessed by all other classes defined inside the same package. Sub-classes defined inside the different packages only access to public and protected members.
Here’s the table to get more clarity.
|Access Modifier||Same class||Same package subclass||Same package non-subclass||Difference Package subclass||Different package non-subclass|
From the above table, you can infer whether data members of a class with certain modifiers can be accessed by:
- The same class in which these data members are defined
- The classes available inside the same package
- The sub-class of this Java file that is stored outside this package
- All other classes are available anywhere inside the system.
Let’s understand them in more detail.
If we make a class named A and define data members inside it with any modifiers (public, protected, default, and private), then we can access them inside class A.
We have single or multiple classes inside a package. Let’s say we’ve two classes inside a package named A and B. If we try to import class A inside class B, then except for private data members of class A all others will be accessible to class B.
Same Package Sub-class
Let's create two classes Class A and B where Class B inherits from Class A. In such a scenario, Class B can access all members of Class A except private members. It can access the default and protected members as it belongs to the same package.
Different Package Sub-class
Say you have two packages, packageA, and packageB. The packageA contains class A and packageB contains class B. Class B is a subclass of class A but since they both are in different packages, that’s why class B can access only public and protected members of class A, default and private members will be hidden.
Let’s say a class B inside a packageB wants to access class A of packageA. Now, class B is NOT a subclass of class A. In this case, only public members of class A will be accessible to class B.
How to Access A Package?
Accessing a package inside another Java program file is required in almost every real-life project (or as soon as you move ahead of the basics of Java).
We use the import keyword to add desired package files into the current Java program. There are mainly three ways to access a package and its files.
Using packageName (dot) *
- Using asterisk (*) made all the classes and interfaces available in the package accessible. One thing to note here is that if a package contains a sub-package, then it’ll NOT be accessed by doing this. We need to import sub-package separately.
- In the above code snippet, we’ve made a class named B with a main() method.
- We’re able to make an object of class A just because we imported packageA and since we’re using * (asterisk), it imports all the files that are defined inside packageA, and class A is one of them.
- By specifying className or another file, only that file will be imported into your current Java file. This is prominent behavior because you usually don’t want to import everything inside a package, just a single file.
- Otherwise, it costs you a lot of memory which may cause other issues. This way of accessing the file is most efficient and widely used.
- In the above code snippet, we’ve made a class named B with a main() method. We can make an object of class A just because we imported class A from packageA.
- Though we’re allowed to make an object of class A and use it, if we tried to make an object of any other class that is defined inside packageA then the Java compiler will definitely not like it and instantly show an error.
- This is because we’re not using * (that imports everything from a package). If we import a single file, then all other files are inaccessible until we import them manually using the same procedure.
Using the Fully Qualified Name
- Imagine a situation where you’ve imported two packages, and both of them have a file of the same name. Don’t you think the advantage of the java packages (prevent name collision) is found to be void here?
- How can a online Java compiler resolve two files of the same name? Now you may get why this option is used to access a particular file.
- So, in short, it’s likely to be used in cases where two or more packages have the same file name, and you want to access each of them.
Handling Naming collision error
Having two classes with the same name in a single file produces a name collision error, but having them on different packages can prevent it. So, packages in Java also help in preventing naming collision errors. See example.
We’ve made two packages, package1 and package2. Both packages contain a file of the same name that is sameFileName.java. Having them inside a single package causes a name collision error, and we use two packages to thwart it.
Advantages of Packages in Java
Increases ease of managing your application. How? See, as we discussed at the beginning, if we separate files and arrange them into appropriate packages (folder), it makes files easily accessible, letting us manage them easily.
Provides an extra layer of protection to your files (discussed later).
Prevents Naming Collision error.
- Packages in Java are a collection of similar Java files such as classes, interfaces, and sub-packages (don't forget the storing data inside a laptop analogy).
- There are two types of packages in Java - In-built packages and user-defined packages.
- Packages have various advantages such as preventing name collision error, ease of manageability, and security.
- We can define the access of a package using the four types of access modifiers defined in Java.