What is the difference between public, protected, package-private and private in Java?

Viewed 2435528

In Java, are there clear rules on when to use each of access modifiers, namely the default (package private), public, protected and private, while making class and interface and dealing with inheritance?

30 Answers

The official tutorial may be of some use to you.


Class Package Subclass
(same pkg)
Subclass
(diff pkg)
World
public + + + + +
protected + + + +
no modifier + + +
private +

+ : accessible
blank : not accessible

(Caveat: I am not a Java programmer, I am a Perl programmer. Perl has no formal protections which is perhaps why I understand the problem so well :) )

Private

Like you'd think, only the class in which it is declared can see it.

Package Private

It can only be seen and used by the package in which it was declared. This is the default in Java (which some see as a mistake).

Protected

Package Private + can be seen by subclasses or package members.

Public

Everyone can see it.

Published

Visible outside the code I control. (While not Java syntax, it is important for this discussion).

C++ defines an additional level called "friend" and the less you know about that the better.

When should you use what? The whole idea is encapsulation to hide information. As much as possible you want to hide the detail of how something is done from your users. Why? Because then you can change them later and not break anybody's code. This lets you optimize, refactor, redesign, and fix bugs without worrying that someone was using that code you just overhauled.

So, the rule of thumb is to make things only as visible as they have to be. Start with private and only add more visibility as needed. Only make public that which is necessary for the user to know, every detail you make public cramps your ability to redesign the system.

If you want users to be able to customize behaviors, rather than making internals public so they can override them, it's often a better idea to shove those guts into an object and make that interface public. That way they can simply plug in a new object. For example, if you were writing a CD player and wanted the "go find info about this CD" bit customizable, rather than make those methods public you'd put all that functionality into its object and make just your object getter/setter public. In this way being stingy about exposing your guts encourages good composition and separation of concerns

I stick with just "private" and "public". Many OO languages just have that. "Protected" can be handy, but it's a cheat. Once an interface is more than private it's outside of your control and you have to go looking in other people's code to find uses.

This is where the idea of "published" comes in. Changing an interface (refactoring it) requires that you find all the code which is using it and change that, too. If the interface is private, well no problem. If it's protected you have to go find all your subclasses. If it's public you have to go find all the code which uses your code. Sometimes this is possible, for example, if you're working on corporate code that's for internal use only it doesn't matter if an interface is public. You can grab all the code out of the corporate repository. But if an interface is "published", if there is code using it outside your control, then you're hosed. You must support that interface or risk breaking code. Even protected interfaces can be considered published (which is why I don't bother with protected).

Many languages find the hierarchical nature of public/protected/private to be too limiting and not in line with reality. To that end, there is the concept of a trait class, but that's another show.

Easy rule. Start with declaring everything private. And then progress towards the public as the needs arise and design warrants it.

When exposing members ask yourself if you are exposing representation choices or abstraction choices. The first is something you want to avoid as it will introduce too many dependencies on the actual representation rather than on its observable behavior.

As a general rule I try to avoid overriding method implementations by subclassing; it's too easy to screw up the logic. Declare abstract protected methods if you intend for it to be overridden.

Also, use the @Override annotation when overriding to keep things from breaking when you refactor.

The most misunderstood access modifier in Java is protected. We know that it's similar to the default modifier with one exception in which subclasses can see it. But how? Here is an example which hopefully clarifies the confusion:

  • Assume that we have 2 classes; Father and Son, each in its own package:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
    
  • Let's add a protected method foo() to Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
    
  • The method foo() can be called in 4 contexts:

    1. Inside a class that is located in the same package where foo() is defined (fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
      
    2. Inside a subclass, on the current instance via this or super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
      
    3. On an reference whose type is the same class:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
      
    4. On an reference whose type is the parent class and it is inside the package where foo() is defined (fatherpackage) [This can be included inside context no. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
      
  • The following situations are not valid.

    1. On an reference whose type is the parent class and it is outside the package where foo() is defined (fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
      
    2. A non-subclass inside a package of a subclass (A subclass inherits the protected members from its parent, and it makes them private to non-subclasses):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }
      

The difference can be found in the links already provided but which one to use usually comes down to the "Principle of Least Knowledge". Only allow the least visibility that is needed.

Java access modifies

enter image description here

Access modifier can be applicable for class, field[About], method. Try to access, subclass or override this.

  • Access to field or method is through a class.
  • Inheritance and Open Closed Principle[About]
    • Successor class(subclass) access modifier can be any.
    • Successor method(override) access modifier should be the same or expand it

Top level class(first level scope) can be public and default. Nested class[About] can have any of them

package is not applying for package hierarchy

[Swift access modifiers]

This page writes well about the protected & default access modifier

.... Protected: Protected access modifier is the a little tricky and you can say is a superset of the default access modifier. Protected members are same as the default members as far as the access in the same package is concerned. The difference is that, the protected members are also accessible to the subclasses of the class in which the member is declared which are outside the package in which the parent class is present.

But these protected members are “accessible outside the package only through inheritance“. i.e you can access a protected member of a class in its subclass present in some other package directly as if the member is present in the subclass itself. But that protected member will not be accessible in the subclass outside the package by using parent class’s reference. ....

David's answer provides the meaning of each access modifier. As for when to use each, I'd suggest making public all classes and the methods of each class that are meant for external use (its API), and everything else private.

Over time you'll develop a sense for when to make some classes package-private and when to declare certain methods protected for use in subclasses.

Differences between public, private, default and protected access modifiers

This image will make you understand easily about the basic differences between public, private, protected and default access modifiers. The default modifier takes place automatically when you don't declare ant access modifiers in your code.

My two cents :)

private:

class -> a top level class cannot be private. inner classes can be private which are accessible from same class.

instance variable -> accessible only in the class. Cannot access outside the class.

package-private:

class -> a top level class can be package-private. It can only be accessible from same package. Not from sub package, not from outside package.

instance variable -> accessible from same package. Not from sub package, not from outside package.

protected:

class -> a top level class cannot be protected.

instance variable -> Only accessible in same package or subpackage. Can only be access outside the package while extending class.

public:

class -> accessible from package/subpackage/another package

instance variable -> accessible from package/subpackage/another package

Here is detailed answer

https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md

  • public

    If a class member is declared with public then it can be accessed from anywhere

  • protected

    If a class member is declared with keyword protected then it can be accessed from same class members, outside class members within the same package and inherited class members. If a class member is protected then it can NOT be accessed from outside package class unless the outside packaged class is inherited i.e. extends the other package superclass. But a protected class member is always available to same package classes it does NOT matter weather the same package class is inherited or NOT

  • default

    In Java default is NOT an access modifier keyword. If a class member is declared without any access modifier keyword then in this case it is considered as default member. The default class member is always available to same package class members. But outside package class member can NOT access default class members even if outside classes are subclasses unlike protected members

  • private

    If a class member is declared with keyword protected then in this case it is available ONLY to same class members

when talking about access modifiers we can easy to understand, very simple rules include them.

Private Access modifier use in: - Only same class

Default Access modifier use in: - Only same class / Same package subclasses

Protected Access modifier use in: - same class / Same package subclasses / Same package non - subclasses / Different package subclasses

Public Access modifier use in:- we can use anywhere (same class / Same package subclasses / Same package non - subclasses / Different package subclasses/ Different package non - subclasses)

Access Specifiers in Java: There are 4 access specifiers in java, namely private, package-private (default), protected and public in increasing access order.

Private: When you are developing some class and you want member of this class not to be exposed outside this class then you should declare it as private. private members can be accessed only in class where they are defined i.e. enclosing class. private members can be accessed on 'this' reference and also on other instances of class enclosing these members, but only within the definition of this class.

Package-private (default): This access specifier will provide access specified by private access specifier in addition to access described below.

When you are developing some package and hence some class (say Class1) within it, you may use default (need not be mentioned explicitly) access specifier, to expose member within class, to other classes within your (same) package. In these other classes (within same package), you can access these default members on instance of Class1. Also you can access these default members within subclasses of Class1, say Class2 (on this reference or on instance of Class1 or on instance of Class2).

Basically, within same package you can access default members on instance of class directly or on 'this' reference in subclasses.

protected: This access specifier will provide access specified by package-private access specifier in addition to access described below.

When you are developing some package and hence some class (say Class1) within it, then you should use protected access specifier for data member within Class1 if you don't want this member to be accessed outside your package (say in package of consumer of your package i.e. client who is using your APIs) in general, but you want to make an exception and allow access to this member only if client writes class say Class2 that extends Class1. So, in general, protected members will be accessible on 'this' reference in derived classes i.e. Class2 and also on explicit instances of Class2.

Please note:

  1. You won't be able to access inherited protected member of Class1 in Class2, if you attempt to access it on explicit instance of Class1, although it is inherited in it.
  2. When you write another class Class3 within same/different package that extends Class2, protected member from Class1 will be accessible on this reference and also on explicit instance of Class3. This will be true for any hierarchy that is extended i.e. protected member will still be accessible on this reference or instance of extended class. Note that in Class3, if you create instance of Class2 then you will not be able to access protected member from Class1 though it is inherited.

So bottom line is, protected members can be accessed in other packages, only if some class from this other package, extends class enclosing this protected member and protected member is accessed on 'this' reference or explicit instances of extended class, within definition of extended class.

public: This access specifier will provide access specified by protected access specifier in addition to access described below.

When you are developing some package and hence some class (say Class1) within it, then you should use public access specifier for data member within Class1 if you want this member to be accessible in other packages on instance of Class1 created in some class of other package. Basically this access specifier should be used when you intent to expose your data member to world without any condition.

use private when you don't want your variables/methods/classes to be visible outside that class. use protected when you want that only the children of this class can use that variables. use public when you want that the variable/class/method should be accessible from anywhere. use package-private when you want your variable/classes/methods to be used inside that package only.

Related