© Vaskaran Sarcar 2020
V. SarcarInteractive Object-Oriented Programming in Javahttps://doi.org/10.1007/978-1-4842-5404-2_7

7. Packages

Vaskaran Sarcar1 
(1)
Bangalore, Karnataka, India
 

Let’s consider a simple scenario. Can you use the same name for different classes in a Java file? No. The compiler would raise an issue and would point toward this naming collision. When you define a class, you need to follow unique naming conventions. In real-world programming, class names should be somewhat meaningful, and there is the possibility that different programmers will opt for class names that are not unique. Then the obvious question is: how can you deal with such situations? Packages can rescue us in these instances.

You can bundle your classes or interfaces inside your own packages. This approach helps you to avoid naming conflicts. To simplify, two classes from two different packages can have the same name. A package can also control the visibility of the package elements. So, it is your choice as to whether you want your classes to be exposed to the outside world.

Note

You can have two different classes with the same name in two different packages, but in the same package you cannot have two classes with the same name. JLS11 gives a nice example, saying that if there is a package named mouse and a member type Button in that package (which then might be referred to as mouse.Button), then there cannot be any package with the fully qualified name mouse.Button or mouse.Button.Click.

In Java, directories are the physical representation of packages. Creating a package in Eclipse is quite easy. You do not even have to worry about how the Java runtime will find the proper packages or classes inside it. However, you may need to pay special attention to the PATH and CLASSPATH environment variables. These variables play important role before you write your first Java program in a command-line environment.

Before you proceed further, remember the following points:
  • The package statement should be at the top of your source file. If you do not explicitly define this statement, then all the classes/interfaces etc. will be located in the current default package.

  • By convention, the name of a package starts with lowercase letters; for example, some of the built-in Java packages are java.lang, java.awt, java.util, java.io, etc.

  • A package can contain subpackages; for example, if you have a package p, and q is a subpackage of p and contains a class, namely, MyClass, then you can refer to MyClass with the fully qualified name p.q.MyClass. So, the name of the package must follow the directory structure.

  • When one class refers to another class inside the same package, the package statement need not be included. Otherwise, you may need to use the fully qualified class name, like packagename.MyClass, or you may need to use import statements.

  • A complete package can be imported as follows:

import packagename.*;
  • Or, if you want to import only a particular class—say, MyClass from a package called mypack—use something like the following:

import mypack.MyClass;
  • Every class in Java resides inside a package. Sometimes you may see Java source files without any package declaration. It means that those classes are inside a default or unnamed package. JLS 11 says the following about unnamed packages: “An ordinary compilation unit that has no package declaration is part of an unnamed package. Unnamed packages are provided by the Java SE Platform principally for convenience when developing small or temporary applications or when just beginning development.”

Creating a Package

In this book, I am using Eclipse IDE. Creating a package in Eclipse is easy. Here are the steps on how to create a package in Eclipse IDE.
  1. 1.
    Click File menu ➤ New ➤ Package (consider Figure 7-1).
    ../images/433474_2_En_7_Chapter/433474_2_En_7_Fig1_HTML.jpg
    Figure 7-1

    Step 1: How to create a Java package in Eclipse editor

     
  2. 2.
    Supply the required information and click Finish (consider Figure 7-2).
    ../images/433474_2_En_7_Chapter/433474_2_En_7_Fig2_HTML.jpg
    Figure 7-2

    Step 2: How to create a Java package in Eclipse editor

     
  3. 3.
    Now you can see the package in the Package Explorer view. For example, it may look like Figure 7-3.
    ../images/433474_2_En_7_Chapter/433474_2_En_7_Fig3_HTML.jpg
    Figure 7-3

    An empty Java package is created

    Note The newly created package is empty. But other packages in the snapshot already have some classes inside them. Those packages were created earlier.

     
  4. 4.
    Now right-click on the package name ➤ New ➤ Class/Package to put classes/subpackages/etc. inside the created package. Once you put one or more classes inside the package, it may look similar to the following. For example, in the following diagram, one class, Demonstration1.java, is placed inside the package java2e.chapter7. But the package java2e.chapter7.companya contains two classes—GoaPackage.java and KeralaPackage.java.
    ../images/433474_2_En_7_Chapter/433474_2_En_7_Fig4_HTML.jpg
    Figure 7-4

    Sample Package Explorer view of non-empty Java packages in Eclipse editor

     

Demonstration 1

Now, let us go through an example. Consider two travel companies, A and B. Company A conducts tours for Goa and Kerala. Company B conducts tours for Goa and Andaman. Any tourist can seek information from them for a particular tour package. As per the naming, in the following example, company A is using the package java2e.chapter7.companya and company B is using java2e.chapter7.companyb package. You can consider Figure 7-4 to understand the overall structure.

Here, I have covered the following scenarios:
  • Less-challenging situation: Only Company A conducts tours for Kerala, and only Company B conducts tours for Andaman.

  • More-challenging situation: Notice that both companies conduct a Goa tour, and you need to get tariff information through the respective GoaPackage.java class. Notice that both packages use the same class name.

// GoaPackage.java [For Company A, in java2e.chapter7.companya package]
package java2e.chapter7.companya;
public class GoaPackage
{
        int basePrice=10000;
        public void showPrice()
        {
                System.out.println("***Tariff for Goa tour in Company A***" );
                System.out.println("For two person , Goa tour package is Rs."+ basePrice*2 );
                System.out.println("For four person , Goa tour package is Rs."+ basePrice*4 );
                System.out.println("**************" );
        }
}
// KeralaPackage.java [For Company A, in java2e.chapter7.companya package]
package java2e.chapter7.companya;
public class KeralaPackage
{
        int basePrice=7000;
        public void showPrice()
        {
                System.out.println("***Tariff for Kerala tour in Company A***" );
                System.out.println("For two person , Kerala tour package is Rs."+ basePrice*2 );
                System.out.println("For four person, Kerala tour package is Rs."+ basePrice*4 );
                System.out.println("**************" );
        }
}
// AndamanPackage.java [For Company B, in java2e.chapter7.companyb package]
package java2e.chapter7.companyb;
public class AndamanPackage
{
        int basePrice=12000;
        public void showTariff()
        {
                System.out.println("***Tariff for Andaman tour in Company B***" );
                System.out.println("In Company B:For two persons, Andaman tour package is Rs."+ basePrice*2 );
                System.out.println("In Company B:For four persons, Andaman tour package is Rs."+ basePrice*4 );
                System.out.println("**************" );
        }
}
// GoaPackage.java [For Company B, in java2e.chapter7.companyb package]
package java2e.chapter7.companyb;
public class GoaPackage {
       int basic_price = 15000;
       int serviceTax = 2000;
       public void showTariff() {
             int forTwoPerson = basic_price * 2 + serviceTax;
             int forFourPerson = basic_price * 4 + serviceTax;
             System.out.println("***Tariff for Goa tour in Company B***");
             System.out.println("In Company B:For two persons , Goa tour package is Rs." + forTwoPerson);
             System.out.println("In Company B:For four persosn , Goa tour package is Rs." + forFourPerson);
             System.out.println("****************");
       }
}
//Demonstration-1
package java2e.chapter7;
import java2e.chapter7.companya.*;
import java2e.chapter7.companyb.*;
/*import java2e.chapter7.companya.GoaPackage;
import java2e.chapter7.companya.KeralaPackage;
import java2e.chapter7.companyb.AndamanPackage;*/
public class Demonstration1 {
       public static void main(String[] args) {
        System.out.println("***Demonstration-1.Exploring packages.***");
        //Only Company-a has KeralaPackage
        KeralaPackage companyAKeralaPackage=new KeralaPackage();
        companyAKeralaPackage.showPrice();
        //Only Company-b has AndamanPackage
        AndamanPackage companyBAndamanPackage=new AndamanPackage();
        companyBAndamanPackage.showTariff();
        //Company-a and company-b both have package tours for Goa.
        java2e.chapter7.companya.GoaPackage companyAGoaPackage=new java2e.chapter7.companya.GoaPackage();
        companyAGoaPackage.showPrice();
        java2e.chapter7.companyb.GoaPackage companyBGoaPackage=new java2e.chapter7.companyb.GoaPackage();
        companyBGoaPackage.showTariff();
       }
}
Output:
***Demonstration-1.Exploring packages.***
***Tariff for Kerala tour in Company A***
For two person , Kerala tour package is Rs.14000
For four person, Kerala tour package is Rs.28000
**************
***Tariff for Andaman tour in Company B***
In Company B:For two persons, Andaman tour package is Rs.24000
In Company B:For four persons, Andaman tour package is Rs.48000
**************
***Tariff for Goa tour in Company A***
For two person , Goa tour package is Rs.20000
For four person , Goa tour package is Rs.40000
**************
***Tariff for Goa tour in Company B***
In Company B:For two persons , Goa tour package is Rs.32000
In Company B:For four persosn , Goa tour package is Rs.62000
****************

Have you noticed an interesting fact? Since the GoaPackage class is available in both Java packages, you needed to use the fully qualified name inside the main() method to refer to the intended class from the particular package. But you did not need to refer to the fully qualified name for the other classes, KeralaPackage or AndamanPackage, since those are classes with unique names.

This example also demonstrates the fact that you will not receive any compile-time errors if you import full packages with star form, where the packages may contain a class with the same name. But while accessing the class, you need to use the fully qualified name of the class. For instance, you must write java2e.chapter7.companya.GoaPackage because the GoaPackage class is available for both companies.

Note

I have kept the dead (commented) code to show you how to import a particular class from a package instead of importing the whole package.

Key Notes About Packages in Java

Here are some important points about packages:
  • All classes in the java.lang package are imported by default. (Q&A 7.3 talks about import statements in detail.)

  • If you want to rename your package, first rename the directory in which your classes are stored.

  • Package naming conventions should be followed carefully; for example, if we use a statement like package a.b.c, we mean to say that directory c is placed inside directory b, which is again placed in inside directory a.

  • You can remember the visibility control mechanism by referring to Table 7.1.

Q&A Session

7.1 If every class stays in a package, then how could I use System.out.print() up to now without importing any packages?

In Java, all classes in the java.lang package are imported by default. This is why you were able to use System.out.println()—the System class also resides inside the default java.lang package.

If you import a package, subpackages will not be imported by default. For example, let’s say there is a subpackage, namely subpacka, in the package companya, and you have following code:
package java2e.chapter7.companya.subpacka;
public class SubGoaPackage {
       int basePrice = 500;
       public void showPrice() {
             System.out.println("**I am in SubGoaPackage.I need to update myself**");
       }
}
Now, if you do not import this subpackage in Demonstration 1, the bold lines in the following code segment will cause compile-time errors:
//Subpackages will not be imported by default.
//Need to import the package explicitly.
//import java2e.chapter7.companya.subpacka.*;
SubGoaPackage companyASubGoaPackage=new SubGoaPackage();
companyASubGoaPackage.showPrice();

Note

If you import a package, subpackages will not be imported by default.

7.2 Can you explain about the default access specifier?

You can always refer to Table 7-1 for your reference. From the table, it is obvious that if you do not mention any specific access modifier, like public, private, etc., with regards to a member, it will be considered to have a default modifier, and then your particular member will be visible inside the same package only; in other words, all other classes inside the package can see and use it.
Table 7-1

Access Protection Chart Using Packages

 

public

protected

private

Default/No modifier

Same class

Yes

Yes

Yes

Yes

Subclass in same package

Yes

Yes

No

Yes

Non-subclass in same package

Yes

Yes

No

Yes

Subclass in different package

Yes

Yes

No

No

Non-subclass in different package (outside world)

Yes

No

No

No

By the same token, you can give visibility to outside classes with a restriction that only those outside classes that are in the same inheritance hierarchy (i.e., subclass) can see the intended member, in which case you can use the modifier protected. And if you do not want to put any restrictions in place at all, simply use the public modifier, and to provide maximum restriction, use the private modifier.

Note

A default or no modifier is also known as a package-private modifier because it provides visibility within the containing package only.

7.3 What is the purpose of import statements?

JLS11 says that an import declaration allows a named type or a static member to be referred to by a simple name that consists of a single identifier.” You bring all classes (or packages) from a specified location to your intended location with the use of import statements . Otherwise, you need to use the fully qualified name. For example, suppose you have a class named MyClass with some methods (for simplicity, let’s say you have used public modifiers only). This class is placed inside a package (or directory), packageb, which, in turn, is placed inside another directory, packagea. Now, you want to reuse those methods/class from a different location. So, as per the directory structure, you need to refer to the class as packagea.packageb.Myclass. So, you can see that it becomes tedious and looks ugly to type the long dot-separated package name first for the classes you need to use. So, in short, you can save a lot of typing and increase the readability of our program by using import statements. Once imported, you can refer to a class by its name only.

7.4 Then technically I can avoid import statements. Is this understanding correct?

Yes, but you have to pay a lot in terms of typing and readability in a real-life programming situation. So, I do not recommend that practice.

7.5 Suppose I have used the same class name inside two packages. And then in some other program, I have imported both packages. Will I face any compiler issues? Also, how can I access a particular class?

First of all, there is no compiler issue. If you have same-named classes in two or more packages, just use their fully qualified names to avoid the conflict. Refer to the program in Demonstration 1. You can see that both of the packages have the class GoaPackage.java, and I have used their fully qualified names inside the main() method.

7.6 In some examples, I see the import statement is the first statement. But you told me that the package statement should be the first statement. I have both, which one should come first?

You must remember that package statements should be the first statements. Then import statements should be placed. See Demonstration 2.

Demonstration 2

Consider the following program, which demonstrates the incorrect order of package and import statements.
import java.util.Date;
package java2e.chapter7;//error
class Demonstration2 {
       public static void main(String[] args) {
             System.out.println("***Demonstration-2.Exploring the order of package and import statements.***");
             Date currentTime = new Date();
             System.out.println(currentTime.toString());
       }
}
The result is a compilation error (Figure 7-5).
../images/433474_2_En_7_Chapter/433474_2_En_7_Fig5_HTML.jpg
Figure 7-5

An output snapshot with error message in the Eclipse editor

Let’s change the order of the package and import statements, like the following:
package java2e.chapter7;//package statement should be the first statement
import java.util.Date;// ok
Now you will get the expected output:
***Demonstration-2.Exploring the order of package and import statements.***
Sat Mar 16 20:53:58 IST 2019

Q&A Session

7.7 Why does Java use this kind of design, where package statements must be placed before import statements?

My personal opinion is that you should always fix a location before you start writing the code. For example, you may decide to create classes for your application. If the classes already exist inside the same package (i.e., in same location), you can refer to it immediately and you do not need an import statement. But if this is not the case, you need to bring those classes into the intended location (and import takes its place). So, it’s like first fixing a location in order to build a house. You never build a house and then change the location. Likewise, if you look carefully, you will find that package naming conventions follow the directory structure of the corresponding bytecode; i.e., your intention is to fix a location first, and then you proceed.

7.8 How can I deal with multiple package statements in a source file?

You can have only one package statement in a source file.

7.9 Sometimes I do not see any package statement at all in a source file. Will I face any compiler issues for that?

No. It means that you are using the current default package.

7.10 I have some idea about the usage of packages. It’ll be helpful if you can summarize the overall usefulness of the packages.

If you look carefully, you can see that packages cover following scenarios:
  • They provide an organized structure, which is very useful for understanding and debugging the program.

  • You can avoid naming collisions by using package statements when different packages contain classes with the same name.

  • With different access modifiers inside packages, you can provide a level of security that is very much required in the real-life software development process.

  • You can reuse the classes that are already written and used in a package of other programs.

7.11 Name some built-in Java packages.

java.lang, java.util, java.io, and java.net are commonly used Java packages.

Troubleshooting Common Errors in Command-line Environment

In this book, Java programs are executed in Eclipse. It is a very user-friendly IDE. But sometimes you may want to compile and run a Java program using only Notepad and the command-line environment, but you may encounter some errors. Actually, programming with packages and then compiling and running those programs using the command line can be challenging. For example, suppose you put your class MyClass inside a package, mypack.pkg. Then, you would need to place the source code file in the subdirectory named pkg inside the directory mypack, which is in turn within the main Java working directory. In addition to this, to compile or run the program, you should be in the main directory, not in the subdirectory. I’ll show you this use case in detail at the end of this section.

To begin with, let’s analyze some fundamental errors in the command-line environment. Suppose you have written the following program and saved it in C:TestClassHello.java:
public class Hello {
       public static void main(String[] args) {
             System.out.println("***Hello Vaskaran***");
       }
}
When you compile it, you may encounter the following error:
C:TestClass>javac Hello.java
'javac' is not recognized as an internal or external command,
operable program or batch file.
This kind of problem occurs when you do not set the environment variables properly. You can set your PATH environment variable to remove this error, as follows:
C:TestClass>set path="C:Program FilesJavajdk1.8.0_172in";
C:TestClass>javac Hello.java
C:TestClass>

But instead of setting this environment variable at the command prompt, it is suggested that you edit your environment variables and add this. It will be a one-time activity for you.

Sometimes you can compile the program but cannot run it. For example, during execution, you may encounter a problem saying: Error: Could not find or load main class XXX, where XXX is the class name. Here is a screenshot of such an event:

../images/433474_2_En_7_Chapter/433474_2_En_7_Figa_HTML.jpg
In my case, a quick fix for this problem was to set the following variables properly (since I installed jdk1.8.0_172 in my system):
C:TestClass>set class="C:Program FilesJavajdk1.8.0_172in";
C:TestClass>set classpath="C:Program FilesJavajre1.8.0_172lib t.jar";
Now I can recompile and run the program again. This time, the program is executed properly.
C:TestClass>javac Hello.java
C:TestClass>java Hello
***Hello Vaskaran***
But in some cases, for a similar error message, you may need to search for other probable causes of failure. For example, let’s modify the program using a package statement at the beginning, as follows:
package mypack;
public class Hello2 {
       public static void main(String[] args) {
             System.out.println("***Hello Vaskaran***");
       }
}
Let’s suppose you put this Hello2.java in C:TestClassmypack. Now, try to compile and run the program as follows:
C:TestClassmypack>javac Hello2.java
C:TestClassmypack>java Hello2
Error: Could not find or load main class Hello2
You can see that this time the program is not running properly. Notice that you are currently in mypack. As said before, in a case like this, you should be in the main directory, not in the subdirectory. So, in this case, you need to go one level up and try the following commands:
C:TestClassmypack>cd ..
C:TestClass>java mypack.Hello2
***Hello Vaskaran***

In short, if you want to use simple command prompts and Notepad to run your Java program, you need to set your PATH and CLASSPATH environment variables properly. In addition to this, if you use a package statement, you should maintain the directory structure properly, and you should run your program by following the correct directory structure.

Summary

This chapter discussed the following topics:
  • What is a package?

  • How can you create packages in Eclipse IDE?

  • How should import statements be used?

  • What restrictions are associated with packages?

  • How can you write simple programs to demonstrate packages in Java?

  • How can you avoid some command-line environment errors?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.49.106