Java Keywords (Part XIII): Import Keyword and the Concept of Java Packages

We are up to 36 keywords covered in previous articles! That's 75% keywords covered. We have only 12 keywords to cover and I will be covering 2 of those in this article. I am so excited about getting to nearly the end of the series. As I mentioned before, knowing the Java keywords and being able to explain their usage correctly, is something that you will most likely need in an entry level Java programmer job interview. If this ever helps one of you, I would love to hear from you! This article will illustrate the use of the keywords import and package. This is going to be a very short article. I promise. I suggest you start with Java Keywords (Part I) before proceeding further, if you have not read any of the previous articles in the Java Keyword series. Also, go back and read the one about Data Types. All of these articles are from September 2018. That should help you find them quickly. You can also use the "search" option at the top of this page. The series was written with natural progression in mind. Therefore, some of the keywords already covered may be used in code examples illustrated here.

Java keyword list

abstract continue for new switch
assert default goto* package synchronized
boolean do if private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const* float native super while
Keyword marked with an asterisk (*) are keywords that, although valid, are not used by programmers.

Packages

The purpose of the keyword package, is to define the namespace for the classes contained in it.

The simplest way to think of a package is as a folder; mainly because it is indeed a folder. We use folders primarily to keep things organized in a logical way. Most computer Operating Systems offer a series of folders out of the box, to help us stayed organized: Photos, Videos, Music, Documents, Desktop. When we want to store photos, it makes sense to store them in the "Photos" folder. We can also create our own subfolders to further organize the contents of a folder. For instance, you may want to store last year's vacation photos in "Vacation 2019" insde the Photos folder. Likewise, we can use packages and sub-packages to compartmentalize our classes in groups that make some logical sense. This partitioning provides a namespace for our classes. Namespaces help with avoiding collisions with other classes that may have the same name; just like you cannot have two files with the same name in the same folder. So, if you need to tell the operating system that you need a certain file, providing the full path and name of the file guarantees that you will get precisely the file you need. In Java, the combination of the package (path) and class name is known as the Canonical Name. For more information on packages, please visit my article on this very topic.

Package view in Eclipse
Going back to the original point, defining a namespace means that classes inside a package have a specific definition that is different than classes with similar name elsewhere. Suppose you have two table classes: package1.Table and package2.Table. Even if these classes do the exact same work, you have to assume they are different from one another for the simple fact that they are defined in different packages. Therefore, instances of one "Table" class are not necessarily compatible with instances of the other "Table" class. More about this "conflict" on the Importing Classes section.

Another benefit of packages, is that serves as a way to encapsulate features of a program or library. For example, there might be classes inside a package that may not be suitable for direct access by external entities. Thefore, declaring these classes with default access modification (see Part I of this series for a refresher) "hides" these classes from the outside. This information hiding helps in keeping your API simpler, by only making visible those classes suitable for external access.

Importing classes

Importing classes mean that you want to bring in (use) functionality that exist in another namespace without having to use the canonical name of a class (or fully qualified name). Obviously, if two classes share the same name that are used in a single class file, you have no choice but to resolve at least one with its fully qualified name. In the previous example of "Table" classes in two different packages:

package package3;

import package1.Table;

public class MyApp {
	
	public static void main (String[] args) {
		Table t1 = new Table();
		package2.Table t2 = new package2.Table();
	}
}

When you import, it is considered a good practice to import only the classes you need from any given package. However, Java supports the use of the asterisk symbol (*) to import all classes inside the named package. It will not import classes in subpackages. In the example above, you cannot import two classes with the same name, even if they are defined in different packages. On the surface, this might not make sense to you. But, if you really think about it, this is necessary because you won't be able to differentiate in the body of a class one type of object from the other. Consider this example:

package package3;

import package1.Table;
import package2.Table; // This import will cause a compiling error

public class MyApp {
	
	public static void main (String[] args) {
		Table t1 = new Table();
		Table t2 = new Table();
	}
}
How will the program know which "Table" class you want to use for objects t1 and t2? If you think you can get around this issue by using import all wildcard on one of the import statements, the code will assume that you want to use the class type that is explicitly declared. If you use the wildcard on both import statements, both t1 and t2 declarations will result in a compiling error until one is explicitly imported and the other one declared with its fully qualified name, just like in the orgininal code snippet.

You may be asking yourself "when do I need to "import"? You need to import classes when they reside outside the declaring class (namespace) package.

Notice on the image above how the IDE is indicating an error with the use of the "MyClass" class. This is because "MyClass" and "MyOtherClass" exist in two different packages. Therefore, if not using "MyOtherClass" fully qualified (canonical) name, I must include an import statement to use it.

/*
 * Programming Corner
 * Professor Fontanez
 * www.professorfontanez.com
 * May 9, 2020: 10:58:09 AM
 */
package package1.subpackage;

import package1.*; // import all classes in package1 (assume MyClass resides in that package)

public class MyOtherClass {
 
 public MyClass myAttrib;
}
An exception to the rule mentioned above, classes from the Java library that reside inside the java.lang package do not need to be imported. The JVM import those classes for you. These classes are essential to the Java language, and by extension, to all programs; being the most noticeable the Object and String classes.

Next up, Part XIV: Using instanceof Operator

Comments

Popular posts from this blog

Implementing Interfaces with Java Records

Customizing Java Records

Exception Handling: File CRUD Operations Example