Menu

Java Access Modifiers: public, private, protected, default

How Java's four access levels - public, private, protected, and package-private - control what other code can see and touch.

This page includes runnable editors - edit, run, and see output instantly.

Who Gets to Touch Your Code

An access modifier is a keyword in front of a class, field, method, or constructor that decides who else is allowed to use it. It's the foundation of encapsulation: you hide the messy internals of a class and expose only the parts you trust other code to call.

Java has four levels, from most open to most locked-down: public, protected, default (no keyword at all), and private. Get these right and a class becomes safe to change later, because nothing outside it depends on details you never promised to keep.

private: Visible Only Inside the Class

private is the tightest level. A private member can only be touched by code written inside the same class - not subclasses, not other classes in the same package, nobody. This is where most of your fields belong.

balance is private, so the only way to change it is through deposit, which refuses negative amounts. If balance were public, any code could write account.balance = -9999 and skip the check entirely. That guard is the whole point of hiding the field.

Try uncommenting account.balance = 500; in main and you'll get a compile error: balance has private access in BankAccount.

public: Visible Everywhere

public is the opposite extreme - anyone, anywhere, can use the member. Your method names that other code is meant to call are usually public. So is the class itself when it needs to be reachable from other packages.

The common pattern - sometimes called the public API of a class - is private fields, public methods. The fields hold state nobody else should poke at; the methods are the controlled doors in and out. getBalance and deposit above are exactly this.

default (Package-Private): No Keyword at All

If you write no modifier, you get default access, also called package-private. The member is visible to every class in the same package and invisible to everything outside it. There is no keyword for this level - the absence of one is the level.

class Invoice {       // no modifier -> visible only within this package
    int amount;       // no modifier -> package-private field
}

This catches a lot of beginners: leaving off public doesn't make something private, it makes it package-private. A field you meant to keep secret is still fully readable and writable by any class that happens to live in the same package. If you want it truly hidden, you must write private explicitly.

Default access is genuinely useful for helper classes that are an implementation detail of one package - you don't export them, but classes that cooperate within the package can still use them freely.

protected: Package Plus Subclasses

protected is one notch looser than default. A protected member is visible everywhere default is (the same package), and also to subclasses - even subclasses in a different package. It's designed for things you want to share with classes that extend yours, but not with the whole world.

Dog reaches into name and sound() because they're protected and Dog is a subclass. Outside code that isn't a subclass and isn't in the package still can't touch them. Reach for protected when you're designing a class meant to be extended; otherwise prefer private.

The Four Levels at a Glance

Here's the full picture, from most restrictive to most open:

ModifierSame classSame packageSubclass (other package)Everywhere
privateyesnonono
defaultyesyesnono
protectedyesyesyesno
publicyesyesyesyes

A simple rule of thumb: start with private and only loosen when something genuinely needs wider access. It's much easier to widen access later than to tighten it once other code has started depending on a member.

Modifiers on Classes Themselves

Access modifiers apply to classes too, not just members - but a top-level class (one not nested inside another) can only be public or default. You can't write a top-level private or protected class.

public class Order { ... }   // reachable from any package
class LineItem { ... }       // default - only this package can see it

A public top-level class must live in a file named after it (Order.java). Nested classes, on the other hand, can use all four modifiers - which is why the examples above could mark inner classes private or default. One subtle point: a public method that returns a package-private type isn't very useful to outside callers, so keep your public surface consistent.

Next: Static Members

So far every field and method here belongs to an instance - you create an object with new and then call methods on it. But sometimes a value or behavior belongs to the class as a whole, shared across every instance, like a counter of how many objects exist. That's what the static keyword is for, and it's up next.

Frequently Asked Questions

What are the four access modifiers in Java?

public, private, protected, and the default (no keyword, also called package-private). public is visible everywhere, private only inside the same class, protected inside the package plus subclasses, and default only inside the same package.

What is the difference between public and private in Java?

public means any code anywhere can access the member. private means only code inside the same class can - subclasses and other classes can't even see it. You usually make fields private and expose them through public methods.

What does it mean when a Java field has no access modifier?

No keyword means default (package-private) access: the member is visible to every class in the same package, but invisible outside it. It's stricter than public but looser than private - and it's easy to leave off by accident, so be deliberate about it.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED