Java Packages

Sandeep Kulange
8 min readDec 26, 2020

Let us learn, how to bundle classes and interfaces into packages, how to use classes that are in packages, and how to arrange your file system so that the compiler can find your source files.

Concept

  • Package is a Java language feature which helps developer to:
  1. To group functionally equivalent or related types together.

2. To avoid naming clashing/collision/conflict/ambiguity in source code.

3. To control the access to types.

4. To make types easier to find( from the perspective of java docs ).

  • Consider following class:
java.lang.Object
//Here java is main package, lang is sub package and Object is type name.
  • If we want to start execution of Java application then we must install JRE on client’s machine. rt.jar and java virtual machine are integral part of JRE. JVM is runtime environment of Java whereas rt.jar is library of core Java which contains compiled code of Java API(.class).
  • rt.jar contains com, java, javax, jdk, org and sun package.
  • java is main package of rt.jar which contains 14 sub packages:

1. applet : Provides the classes necessary to create an applet and the classes an applet uses to communicate with its applet context.

2. awt : Contains the classes for creating GUI and for painting graphics and images.

3. beans : Contains classes related to developing beans.

4. io : Contains classes for IO through streams, serialization and the file system.

5. lang : Contains classes that are fundamental to the design of the Java language.

6. math : Provides classes for performing arbitrary-precision integer arithmetic (BigInteger) and arbitrary-precision decimal arithmetic (BigDecimal).

7. net : Provides the classes for implementing networking applications.

8. nio : Defines buffers, which are containers for data, and provides an overview of the other NIO packages.

9. rmi : Contains types related to distributed programming.

10. security : Provides the classes and interfaces for the security framework.

11. sql : Provides the API for accessing and processing data stored in a data source.

12. text : Provides classes and interfaces for handling text, dates, numbers, and messages in a manner independent of natural languages.

13. time : The main API for dates, times, instants, and durations.

14. util : Contains the collections framework, legacy collection classes, event model, date and time facilities, internationalization, and miscellaneous utility classes (a string tokenizer, a random-number generator, and a bit array).

Package Members

  • Not necessarily but as shown below, package can contain some or all types.
  1. Sub packages
  2. Interfaces
  3. Classes
  4. Enums
  5. Exceptions
  6. Errors
  7. Annotation Types

Package creation

  • package is a keyword in Java.
  • To define type inside package, it is mandatory write package declaration statement inside .java file.
  • Package declaration statement must be first statement inside .java file. Consider following example:
package p1;
class Program{
//TODO
}
  • If we define any type inside package then it is called as packaged type otherwise it wll be unpackaged type.
  • If we define any type inside package then it is called as packaged type otherwise it wll be unpackaged type.
  • Any type can be member of single package only.
package p1, p2; //NOT OK
class Program{
//TODO
}
  • Following code snippet will help us in declaration of package:
package p1; //OK
package p2; //NOT OK
class Program{
//TODO
}
package p3; //Not OK

Unnamed package

  • If we define any type without package then it is considered as member of unnamed/default package.
  • Unnamed packages are provided by the Java SE platform principally for convenience when developing small or temporary applications or when just beginning development.
  • An unnamed package cannot have subpackages.
  • In following code, class Program is a part of unnamed package.
class Program{
public static void main(String[] args) {
System.out.println("Hello");
}
}

Naming convention

  • For small programs and casual development, a package can be unnamed or have a simple name, but if code is to be widely distributed, unique package names should be chosen using qualified names.
  • Generally Package names are written in all lower case to avoid conflict with the names of classes or interfaces.
  • Companies use their reversed Internet domain name to begin their package names. For example : com.example.mypackage
  • Following examples will help you in deciding name of package:
  1. java.lang.reflect.Proxy
  2. oracle.jdbc.driver.OracleDriver
  3. com.mysql.jdbc.cj.Driver
  4. org.cdac.sunbeam.dac.utils.Date

How to use package members in different package?

  • If we want to use types declared inside package anywhere outside the package then

1. Either we should use fully qualified type name

2. Or import statement.

  • If we are going to use any type infrequently then we should use fully qualified name.
  • Let us see how to use type using package name
class Program{
public static void main(String[] args) {
java.util.Scanner sc = new java.util.Scanner( System.in );
}
}
  • If we are going to use any type frequently then we should use import statement. Let us see how to import Scanner.
import java.util.Scanner;
class Program{
public static void main(String[] args) {
Scanner sc = new Scanner( System.in );
}
}
  • There can be be any number of import statements after package declaration statement
  • With the help of( * ) we can import entire package.
import java.util.*;
class Program{
public static void main(String[] args) {
Scanner sc = new Scanner( System.in );
}
}
  • Another, less common form of import allows us to import the public nested classes of an enclosing class. Consider following code.
import java.lang.Thread.State;
class Program{
public static void main( String[] args ){
Thread thread = Thread.currentThread( );
State state = thread.getState( );
}
}

Note : java.lang package contains fundamental types of core java. This package is by default imported in every .java file hence to use type declared in java.lang package, import statement is optional.

Path and Classpath

  • An environment variable is a variable whose value is set outside the program, typically through functionality built into the operating system.

Path

  • In context of Java, path is an OS platform’s environment variable which is used to locate Java language tools.
  • Let us learn, how to set path system variable

Microsoft Windows

  • In Microsoft Windows operating system, generally “C:\Program Files\Java” directory contains jdk and jre installation directory.
  • How to view value of path from terminal?
path
  • Language tools are available in “jdk\bin”. To compile .java file in windows we must set path of bin from any directory on terminal.
set path="c:\Program Files\Java\jdk1.8.0_261\bin";
  • If we close the terminal then we must set it again.
  • Without setting path, if we try to compile the program then we get following error.
'javac' is not recognized as an internal or external command, operable program or batch file.

Linux

  • How to view value of path?
echo $PATH
  • How to set Java path from terminal
export PATH=/usr/bin

Classpath

  • Classpath is Java platform’s environment variable which is used to locate .jar and .class files.

Microsoft Windows

  • Let us see how to set classpath in Windows from terminal:
set classpath=./bin;
  • How to view classpath?
set classpath

Linux

  • Let us see how to set classpath in Linux from terminal:
export CLASSPATH=./bin
  • How to view classpath?
echo $CLASSPATH

Package Examples:

Example No 1

//Location : ./src/Complex.java
package p1;
class TComplex{
@Override
public String toString( ){
return "TComplex.toString()";
}
}
//Location : ./src/Program.java
import p1.TComplex;
class Program{
public static void main(String[] args) {
//p1.TComplex c1 = new p1.TComplex( ); //or
TComplex c1 = new TComplex( );
System.out.println( c1.toString( ) );
}
}
  • Let us compile above code:
javac -d ./bin ./src/Complex.java   //output : p1/TComplex.classexport CLASSPATH=./binjavac -d ./bin ./src/Program.java   //Output : Error//TComplex is not public in p1; can not be accessed from outside package
  • Package name is physically mapped to the folder.
  • Point to Remember : default access modifier of any type is package level private which is also called as default.
//location  :   ./src/Complex.java
??? class TComplex{ //here ??? means package level private / default
//TODO
}
  • If we want to use any type inside same package as well as in different package then access modifier of type must be public.
  • Access modifier of type(class/interface) can be either package level private/public only. In other words, type can not be private or protected.
//location  :   ./src/Complex.java
public class TComplex{
//TODO
}
  • If we compile then compiler generates error.
error:class TComplex is public, should be declared in a file named TComplex.java
  • According to Java Language Specification(JLS), name of public type and name of .java file must be same. It means that, .java file can contain multiple non public types but only one public type.
//location  :   ./src/Complex.java
public class Complex{ //Now OK
@Override
public String toString( ){
return "Complex.toString()";
}
}
  • Let us recompile above code:
javac -d ./bin ./src/Complex.java   //output : p1/Complex.classexport CLASSPATH=./binjavac -d ./bin ./src/Program.java   //Output : Program.classjava Program    //Output : Complex.toString()
  • Conclusion : It is possible to use packaged type from unpackaged type.

Example No 2

//Location : ./src/Complex.java
public class Complex{ //Unpackaged Type
@Override
public String toString( ){
return "Complex.toString()";
}
}
//Location : ./src/Program.java
package p1;
public class Program{
public static void main(String[] args) {
Complex c1 = new Complex( );
System.out.println( c1.toString( ) );
}
}
  • Let us compile above code:
javac -d ./bin ./src/Complex.java   //OK:Complex.classexport CLASSPATH=./binjavac -d ./bin ./src/Program.java   //error : cannot find symbol
  • If we define any type without package then it is considered as a member of default package.
  • Conclusion : Since we can not import default package, it is not possible to use unpackaged type from packaged type.

Example No 3

//Location : ./src/Complex.java
package p1;
public class Complex{
@Override
public String toString( ){
return "Complex.toString()";
}
}
//Location : ./src/Program.java
package p2;
import p1.Complex;
public class Program{
public static void main(String[] args) {
Complex c1 = new Complex( );
System.out.println( c1.toString( ) );
}
}
  • Let us compile above code:
javac -d ./bin ./src/Complex.java   //OK:p1/Complex.classexport CLASSPATH=./binjavac -d ./bin ./src/Program.java   //OK:p2/Program.class//java Program  //Errorjava p2.Program //Complex.toString()
  • Conclusion : We can define types into separate package. It is possible to use packaged type from another packaged type.

Example No 4

//Location : ./src/Complex.java
package p1;
public class Complex{
@Override
public String toString( ){
return "Complex.toString()";
}
}
//Location : ./src/Program.java
package p1;
import p1.Complex; //Optional
public class Program{
public static void main(String[] args) {
Complex c1 = new Complex( );
System.out.println( c1.toString( ) );
}
}
  • Let us compile above code:
javac -d ./bin ./src/Complex.java   //OK:p1/Complex.classexport CLASSPATH=./binjavac -d ./bin ./src/Program.java   //OK:p1/Program.classjava p1.Program //Complex.toString()
  • Conclusion : We can define all types into single package. In this case, to use one type into another type, use of import statement is optional.

Example No 5

//Location : ./src/Complex.java
package p1.p2;
public class Complex{
@Override
public String toString( ){
return "Complex.toString()";
}
}
//Location : ./src/Program.java
package p1.p3;
import p1.p2.Complex;
public class Program{
public static void main(String[] args) {
Complex c1 = new Complex( );
System.out.println( c1.toString( ) );
}
}
  • Let us compile above code:
javac -d ./bin ./src/Complex.java   //OK:p1/p2/Complex.classexport CLASSPATH=./binjavac -d ./bin ./src/Program.java   //OK:p1/p3/Program.classjava p1.p3.Program //Complex.toString()
  • Conclusion : We can create package inside package. It is also called as sub package.

Static Import

  • If static members belonging to the same class then use of typename and dot operator is optional.
  • Consider Following code:
package p1;
public class Program{
private static int number = 10;
public static void main(String[] args) {
System.out.println("Number : "+Program.number); //OK
System.out.println("Number : "+number); //OK : 10
}
}
  • If static members belonging to the different class then use of typename and dot operator is mandatory.
  • PI and pow are static members of java.lang.Math class. To use Math class import statement is not required.
  • Consider Following code:
package p1;
public class Program{
public static void main(String[] args) {
float radius = 10.5f;
float area = ( float )( Math.PI * Math.pow( radius, 2 );
System.out.println( "Area : "+area );
}
}
  • There are situations where you need frequent access to static final fields (constants) and static methods from one or two classes. Prefixing the name of these classes over and over can result in cluttered code. The static import statement gives you a way to import the constants and static methods that you want to use so that you do not need to prefix the name of their class.
  • Consider Following code:
package p1;
import static java.lang.System.out;
import static java.lang.Math.*;
public class Program{
public static void main(String[] args) {
float radius = 10.5f;
float area = ( float )( PI * pow( radius, 2 );
out.println( "Area : "+area );
}
}

References

https://docs.oracle.com/javase/tutorial/java/package/index.html

https://docs.oracle.com/javase/specs/jls/se8/html/jls-7.html

--

--