Course topics

By WebNest Studio Engineering Team

Java - Core Tutorial

Packages and Access Modifiers

A package is a namespace that groups related classes and interfaces together, similar to a folder structure. Packages prevent naming collisions (two classes can both be named Utils if they live in different packages) and provide the boundary that Java's access modifiers use to control visibility.

Java offers exactly four access levels, and only one of them — default — has no keyword at all; it is simply what you get by omitting a modifier.

Why it matters

Access modifiers decide who is allowed to depend on each part of your code. Anything public becomes a promise you have to keep; anything private can be changed freely. Choosing the narrowest level that works is one of the cheapest ways to keep a codebase maintainable, and the four levels are asked about in almost every Java interview.

Watch: Java Access Modifiers Explained 🔐 public vs private vs protected vs default | Java Core

Learn how Java’s public, private, protected, and package-private access levels control visibility across classes and packages, with practical examples.

Watch on YouTube

Declaring and Using Packages

A package declaration, if present, must be the very first non-comment line in a source file: package com.webnest.util;. Classes in other packages access it with an import statement, such as import com.webnest.util.Helper;, or by using the fully qualified name inline.

The Four Access Modifiers

Each modifier controls visibility at a different scope, from the most restrictive to the most open.

  • private — accessible only within the same class.
  • default (package-private) — no keyword; accessible within the same package only.
  • protected — accessible within the same package, plus subclasses in other packages (through inheritance).
  • public — accessible from anywhere, in any package.

Visibility Table

The relationship between modifier and accessible scope is fixed and worth memorizing exactly.

  • private: same class only.
  • default: same class, same package.
  • protected: same class, same package, subclass (even in a different package).
  • public: same class, same package, subclass, and any other package.

Example

A package-private helper class used only within its own package

Java
package com.webnest.util;

class InternalHelper { // package-private (default) class, not visible outside this package
    static int square(int n) {
        return n * n;
    }
}

public class MathTool {
    public static int squareOfSum(int a, int b) {
        return InternalHelper.square(a + b);
    }

    public static void main(String[] args) {
        System.out.println(MathTool.squareOfSum(2, 3));
    }
}
Output
25

Common Mistakes

  • Assuming "default" access means "public by default" — it actually means restricted to the same package, which is more limited than public.
  • Marking a field protected expecting only subclasses to see it, forgetting protected also grants access to every class in the same package.
  • Placing two unrelated top-level public classes in one file, which is not allowed — only one public top-level class per file.
  • Forgetting to import a class from another package and expecting the fully qualified name and the simple name to be interchangeable without an import.

Exercise

Everything in Wallet is public, so any code could set the balance directly. Tighten the access: make the field and the helper method private and keep only deposit and getBalance available to other classes. The output must not change.

Expected output: 500

Java · starter code
class Wallet {
    public int balance;

    public boolean isValid(int amount) {
        return amount > 0;
    }

    public void deposit(int amount) {
        if (isValid(amount)) {
            balance += amount;
        }
    }

    public int getBalance() {
        return balance;
    }
}

public class WalletDemo {
    public static void main(String[] args) {
        Wallet wallet = new Wallet();
        wallet.deposit(500);
        wallet.deposit(-200);
        System.out.println(wallet.getBalance());
    }
}
Show hints
  • Ask of each member: does code outside this class need it? If not, make it private.
  • isValid is only used inside deposit, so it is an internal helper.
Show solution
Java · solution
class Wallet {
    private int balance;

    private boolean isValid(int amount) {
        return amount > 0;
    }

    public void deposit(int amount) {
        if (isValid(amount)) {
            balance += amount;
        }
    }

    public int getBalance() {
        return balance;
    }
}

public class WalletDemo {
    public static void main(String[] args) {
        Wallet wallet = new Wallet();
        wallet.deposit(500);
        wallet.deposit(-200);
        System.out.println(wallet.getBalance()); // 500
    }
}

Quick quiz

1. A member is declared with no access modifier. Where is it visible?

  • A. Everywhere
  • B. Only inside its own class
  • C. In the same package and in all subclasses
  • D. Only within the same package
Show answer

D. No modifier means package-private (default) access: any class in the same package can use it, and nothing outside can.

2. Where is a protected member visible?

  • A. In the same package, and in subclasses in other packages
  • B. Only in subclasses
  • C. Everywhere
  • D. Only in its own class
Show answer

A. protected is package access plus access from subclasses, even when those subclasses are in a different package.

3. Which access modifiers are allowed on a top-level class?

  • A. All four
  • B. protected or private
  • C. public or private
  • D. public or no modifier
Show answer

D. A top-level class can be public or package-private. private and protected apply only to members and nested classes.

Interview questions

What are the four access levels in Java, from most to least restrictive?

Show answer

private: visible only inside the declaring class. Default (no modifier, also called package-private): visible within the same package. protected: visible within the same package and to subclasses in any package. public: visible everywhere.

What is the purpose of packages?

Show answer

Packages group related classes, which keeps large codebases organised. They prevent naming conflicts, because two classes with the same simple name can exist in different packages. And they form an access boundary: package-private members are shared between classes that work together while staying hidden from everything else.

Key Points to Remember

  • Packages group related types and prevent name collisions; the package declaration must be the first line.
  • Four access levels exist: private, default (package-private), protected, and public.
  • protected extends package access to subclasses in other packages as well.
  • public is the only modifier that grants access from completely unrelated packages.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering