OCA Java SE 8 Building Blocks - Package and Imports








Java puts classes in packages. Packages are logical groupings for classes. Java classes are grouped into packages.

We need to tell which packages to search a class when using them in the code with import statement.

Import statements tell Java which packages to search sfor classes.

import java.util.Random;  // import tells us where to find Random 

public class Main { 
  public static void main(String[] args) { 
    Random r = new Random();    
    System.out.println(r.nextInt(10));  // print a number between 0 and 9 
   } 
} 

The import statement tells the compiler which package to look in to find a class.

Package names are hierarchical like the mailing address.

If a package begins with java or javax, this means it came with the JDK.

If it starts with something else, it likely shows where it came from using the website name in reverse.

From example, com.java2s.javaexam tells us the code came from java2s.com.

After the website name, you can add whatever you want.

For example, com.java2s.java8.myname also came from java2s.com.

Java calls more detailed packages child packages.

com.java2s.javaexam is a child package of com.java2s.

The code above generates the following result.





Wildcards

We can use wildcard to to import all the classes in a package:

import java.util.*;    // imports java.util.Random among other things 

public class Main { 
  public static void main(String[] args) { 
    Random r = new Random(); 
    System.out.println(r.nextInt(10)); 
  } 
} 

In the code above, we imported java.util.Random and a list of other classes.

The * is a wildcard that matches all classes in the package.

Every class in the java.util package is available to this program when Java compiles it.

It doesn't import child packages, fields, or methods; it imports only classes.

The code above generates the following result.





Redundant Imports

There's one special package in the Java world called java.lang.

This package is automatically imported.

You can still type this package in an import statement, but you don't have to.

In the following code, how many of the imports do you think are redundant?

import java.lang.System; 
import java.lang.*; 
import java.util.Random; 
import java.util.*; 
//w ww.  j av a 2s  .  c om
public class Main { 
     public static void main(String[] args) { 
           Random r = new Random(); 
           System.out.println(r.nextInt(10)); 
     } 
} 

Three of the imports are redundant.

import java.lang.System; and import java.lang.*; are redundant because everything in java.lang is automatically imported.

For import java.util.Random; and import java.util.*; you just need one.

Java automatically looks in the current package for other classes therefor we do not need to import the classes from the same folder or package.

We cannot use wildcards in the middle as follows

import java.nio.*.*;

And we cannot use wildcards to import methods as follows

import java.nio.files.Paths.*;

The code above generates the following result.

Naming Conflicts

We can use packages to distinguish two classes with the same name.

Java has two Date classes. One is java.util.Date and the other is java.sql.Date.

When a class is found in multiple packages, Java gives you the compiler error.

We can use the following import statements to include the two Java Date classes.

import java.util.Date; 
import java.sql.Date; 

The following code shows how to use the two Date class with full qulified name

import java.util.Date; 

public class Main { 

         Date date; 

         java.sql.Date sqlDate; 

} 

Or you could have neither with an import and always use the fully qualified class name:

public class Main { 

         java.util.Date date; 

         java.sql.Date sqlDate; 

} 

Creating a New Package

The directory structure on your computer is related to the package name.

Suppose we have these two classes:

C:\temp\packagea\ClassA.java
package packagea; 

public class ClassA { 
} 
C:\temp\packageb\ClassB.java
package packageb; 

import packagea.ClassA; 

public class ClassB { 
  public static void main(String[] args) { 
    ClassA a; 
    System.out.println("Got it"); 
  } 
} 

When you run a Java program, Java knows where to look for those package names. In this case, running from C:\temp works because both packagea and packageb are underneath it.

Compiling Code with Packages

Create the two files:

C:\temp\packagea\ClassA.java  
C:\temp\packageb\ClassB.java 

Then type this command:

cd C:\temp

Mac/Linux Setup

Create the two files:

/tmp/packagea/ClassA.java  
/tmp/packageb/ClassB.java 

Then type this command:

cd /tmp 

To Compile

Type this command:

javac packagea/ClassA.java packageb/ClassB.java

If the command does work, two new files will be created:

packagea/ClassA.class and packageb/ClassB.class.

To Run

Type this command:

java packageb.ClassB 

You might have noticed we typed ClassB rather than ClassB.class.

Class Paths and JARs

You can specify the location of the other files explicitly using a class path to reference the class files located some where else or in special JAR files.

A JAR file is like a zip file with mainly Java class files.

On Windows, you type the following:

java -cp ".;C:\temp\someOtherLocation;c:\temp\myJar.jar" myPackage.MyClass 

And on Mac OS/Linux, you type this:

java -cp ".:/tmp/someOtherLocation:/tmp/myJar.jar" myPackage.MyClass 

The dot is here to include the current directory in the class path.

The rest is to look for class files (or packages) in someOtherLocation and within myJar.jar.

Windows uses semicolons to separate parts of the class path; other operating systems use colons.

Finally, you can use a wildcard * to match all the JARs in a directory. Here's an example:

java -cp "C:\temp\directoryWithJars\*" myPackage.MyClass 

This command will add all the JARs to the class path that are in directoryWithJars. It won't include any JARs in the class path that are in a subdirectory of directoryWithJars.