DEV Community

Rajesh Bhola
Rajesh Bhola

Posted on

Part 1: Understanding Package, Import, and Class Declarations

Every Java program follows a specific structure.

Whether you're writing a simple "Hello, World!" program or a large enterprise application with thousands of classes, every Java source file follows the same basic layout.

Understanding this structure helps you organize code correctly and avoid common compile-time errors.

In this article, we'll explore:

  • The structure of a Java source file
  • The purpose of the import statement
  • Types of imports
  • How Java resolves class names
  • Common interview questions
  • Best practices

What Is a Java Source File?

A Java source file is simply a file with the .java extension.

Example

Student.java
OrderService.java
Employee.java
Enter fullscreen mode Exit fullscreen mode

Every Java source file contains Java source code that is compiled into bytecode (.class files).


Structure of a Java Source File

A Java source file can contain three sections, always in this order:

1. Package statement     (optional)
2. Import statements     (optional)
3. Class / Interface / Enum / Record declarations
Enter fullscreen mode Exit fullscreen mode

Visual representation

---------------------------------
Package Statement
---------------------------------
Import Statements
---------------------------------
Class / Interface Declarations
---------------------------------
Enter fullscreen mode Exit fullscreen mode

The order is important.

Changing it may result in compile-time errors.


Section 1: Package Statement

The package statement is optional.

If present, it must be the first non-comment statement in the file.

Example

package com.rajesh.learning;
Enter fullscreen mode Exit fullscreen mode

We'll explore packages in detail in Part 3 of this series.


Section 2: Import Statements

Import statements tell the compiler where to find classes that belong to other packages.

Example

import java.util.ArrayList;
Enter fullscreen mode Exit fullscreen mode

Without imports, we'd have to write fully qualified class names everywhere.


Section 3: Class Declarations

Finally, we define classes, interfaces, enums, or records.

Example

public class Student {

}
Enter fullscreen mode Exit fullscreen mode

A source file may contain multiple classes, although only one public class is allowed per file.


A Complete Example

package com.rajesh.learning;

import java.util.ArrayList;

public class Student {

    public static void main(String[] args) {

        ArrayList<String> names = new ArrayList<>();

        names.add("Rajesh");

        System.out.println(names);

    }

}
Enter fullscreen mode Exit fullscreen mode

Notice the order:

  1. Package
  2. Import
  3. Class

Is an Empty Java File Valid?

Surprisingly, yes.

An empty source file is still a valid Java program.

Enter fullscreen mode Exit fullscreen mode

It compiles successfully.

Of course, it doesn't do anything.


Why Do We Need Import Statements?

Consider the following program.

public class Student {

    public static void main(String[] args) {

        ArrayList<String> students = new ArrayList<>();

    }

}
Enter fullscreen mode Exit fullscreen mode

Compile-time error

cannot find symbol
symbol: class ArrayList
Enter fullscreen mode Exit fullscreen mode

The compiler doesn't know where ArrayList is located.


Solution 1: Fully Qualified Class Name

Instead of importing the class, we can write its complete name.

public class Student {

    public static void main(String[] args) {

        java.util.ArrayList<String> students =
                new java.util.ArrayList<>();

    }

}
Enter fullscreen mode Exit fullscreen mode

This works perfectly.

However, the code becomes lengthy and difficult to read.


Solution 2: Import Statement

A better approach is to import the class once.

import java.util.ArrayList;

public class Student {

    public static void main(String[] args) {

        ArrayList<String> students = new ArrayList<>();

    }

}
Enter fullscreen mode Exit fullscreen mode

Now we can use the short class name throughout the file.


Benefits of Import Statements

Imports make code:

  • Shorter
  • Cleaner
  • Easier to read
  • Easier to maintain

Types of Import Statements

Java provides two types of imports.


1. Explicit Class Import

Imports a single class.

import java.util.ArrayList;
Enter fullscreen mode Exit fullscreen mode

Example

import java.util.ArrayList;

public class Student {

    public static void main(String[] args) {

        ArrayList<String> students = new ArrayList<>();

    }

}
Enter fullscreen mode Exit fullscreen mode

This is the recommended approach.

It clearly tells readers which class is being used.


2. Wildcard Import

Imports all public classes from a package.

import java.util.*;
Enter fullscreen mode Exit fullscreen mode

Example

import java.util.*;

public class Student {

    public static void main(String[] args) {

        ArrayList<String> students = new ArrayList<>();

        HashMap<Integer, String> map = new HashMap<>();

    }

}
Enter fullscreen mode Exit fullscreen mode

Although convenient, wildcard imports make it less obvious which classes are actually used.


Does Wildcard Import Import Subpackages?

No.

This is a common interview question.

import java.util.*;
Enter fullscreen mode Exit fullscreen mode

Imports classes like:

  • ArrayList
  • HashMap
  • Collections
  • Scanner

But it does not import classes from subpackages.

For example,

java.util.concurrent
Enter fullscreen mode Exit fullscreen mode

is not imported.

You must import it separately.

import java.util.concurrent.ConcurrentHashMap;
Enter fullscreen mode Exit fullscreen mode

Fully Qualified Name vs Import

These two programs are equivalent.

Using a fully qualified name

java.util.ArrayList<String> students =
        new java.util.ArrayList<>();
Enter fullscreen mode Exit fullscreen mode

Using an import

import java.util.ArrayList;

ArrayList<String> students = new ArrayList<>();
Enter fullscreen mode Exit fullscreen mode

If you use the fully qualified name, an import is unnecessary.


Ambiguous Imports

Consider this example.

import java.util.*;
import java.sql.*;

public class Demo {

    public static void main(String[] args) {

        Date today = new Date();

    }

}
Enter fullscreen mode Exit fullscreen mode

Compile-time error

reference to Date is ambiguous
Enter fullscreen mode Exit fullscreen mode

Why?

Because Java finds two different classes:

  • java.util.Date
  • java.sql.Date

The compiler doesn't know which one you mean.


How to Resolve Ambiguity

Use the fully qualified name.

java.util.Date today = new java.util.Date();
Enter fullscreen mode Exit fullscreen mode

or

java.sql.Date today =
        new java.sql.Date(System.currentTimeMillis());
Enter fullscreen mode Exit fullscreen mode

Another Common Example

Many beginners accidentally import both:

java.awt.List
Enter fullscreen mode Exit fullscreen mode

and

java.util.List
Enter fullscreen mode Exit fullscreen mode

Using

List list;
Enter fullscreen mode Exit fullscreen mode

will produce an ambiguity error.


How Does Java Resolve Class Names?

When the compiler sees a class name, it searches in this order.

  1. Explicit imports
  2. Classes in the current package
  3. Wildcard imports

Understanding this order explains many interview questions.


Packages Imported Automatically

Every Java program automatically imports the following package.

java.lang
Enter fullscreen mode Exit fullscreen mode

That's why we can write

String
System
Math
Object
Integer
Enter fullscreen mode Exit fullscreen mode

without importing them.

For example,

String name = "Rajesh";
Enter fullscreen mode Exit fullscreen mode

works without

import java.lang.String;
Enter fullscreen mode Exit fullscreen mode

because java.lang is imported automatically.


Are Imports a Runtime Feature?

No.

Imports exist only during compilation.

They help the compiler resolve class names.

At runtime, the JVM uses the compiled bytecode.

Therefore:

  • More imports may slightly increase compile-time work.
  • Imports do not affect runtime performance.

Common Beginner Mistakes

Forgetting to Import a Class

ArrayList<String> list = new ArrayList<>();
Enter fullscreen mode Exit fullscreen mode

Compile-time error if ArrayList isn't imported.


Assuming Wildcard Imports Include Subpackages

Incorrect

import java.util.*;
Enter fullscreen mode Exit fullscreen mode

does not import

java.util.concurrent
Enter fullscreen mode Exit fullscreen mode

Importing Two Classes with the Same Name

import java.sql.*;
import java.util.*;
Enter fullscreen mode Exit fullscreen mode

Using

Date date;
Enter fullscreen mode Exit fullscreen mode

causes an ambiguity error.


Importing Unused Classes

Modern IDEs automatically remove unused imports.

Keeping imports clean improves readability.


Interview Questions

Can a Java source file contain multiple import statements?

Yes.

There is no limit.


Can a Java source file contain multiple package statements?

No.

Only one package statement is allowed.


Does a wildcard import include subpackages?

No.

Only classes in that package are imported.


Is java.lang imported automatically?

Yes.

Every Java program imports java.lang by default.


Are imports a compile-time concept or runtime concept?

Compile-time concept.


Best Practices

  • Prefer explicit imports over wildcard imports.
  • Remove unused imports.
  • Avoid importing classes with the same simple name.
  • Use fully qualified names only when necessary.
  • Let your IDE manage imports automatically.

Quick Memory Trick 🧠

Remember PIC:

  • P → Package
  • I → Imports
  • C → Class

Always write Java source files in this order:

Package
Imports
Class
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • Every Java source file follows a fixed structure.
  • The order is Package → Imports → Class declarations.
  • Imports make code shorter and more readable.
  • Java supports explicit and wildcard imports.
  • Wildcard imports do not include subpackages.
  • java.lang is imported automatically.
  • Imports are used only during compilation.
  • Ambiguous imports occur when multiple packages contain classes with the same name.

If you found this guide helpful, leave a ❤️ and follow for more beginner-friendly Java tutorials, interview questions, and practical coding examples.

Happy Coding!

Top comments (0)