Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`public` modifier in package-private classes

Tags:

java

Recently, I was writing a class that I decided to be package-private (that is, no access modifier, or the default one). It has an inner class and some private helper methods, and one method intended to be used by a class in the same package. All of these class members are static. But then I had a thought: should this one method have the public access modifier or no access modifier, like the class containing it?

On one hand, since the class itself is package-private, it can only be accessed and used within its package, so there is no practical reason to make the method public. But at the same time, semantically, this method is intended to be a public feature of the class, that is, a feature of the class intended to be used externally, so it would make sense to modify its access as such.

For those that like to see code,

final class DummyRemover {

    private DummyRemover() {

    }

    public static int remove(Map<String, ClassNode> classMap) {
        return 0;
    }

    // ...
}

or,

final class DummyRemover {

    private DummyRemover() {

    }

    // Notice the modifier.
    static int remove(Map<String, ClassNode> classMap) {
        return 0;
    }

    // ...
}

What is the best choice here? Is there a rule of thumb for deciding what access modifiers to use in a case like this?

like image 767
Martin Tuskevicius Avatar asked Feb 22 '16 08:02

Martin Tuskevicius


People also ask

Can a package-private class have public methods?

Yes. Well, obviously you can access those methods from within the same class.

What is package-private access modifier?

package-private (often just called package) means that other members of the same package have access to the item. package-private is the default access modifier and does not have a keyword, because package is used to specify the package for a class or interface.

What is private and public specifier related to package?

Public is a keyword denoting that that particular item can be accessed outside the package. Private means that the item will only be used internally in the package.

Can you use the private modifier on classes?

Private access modifier cannot be used for classes and interfaces. The scope of private entities (methods and variables) is limited to the class in which they are declared. A class with a private constructor cannot create an object of the class from any other place like the main method.


2 Answers

There are two reasons why a method should have a higher visibility than its enclosing class:

1. The enclosing class is a base class

... which is intended for extension by subclasses, which might eventually be public, and the method at hand is supposed to be publicly available. E.g.

abstract class Base {
    public void x() {}
}

public class Sub extends Base {
}

// Now, everyone can call:
new Sub().x();

usually, however, if this is your intention, you will declare your method x() in an interface anyway. Even if you don't declare x() in an interface, design-wise, it's probably better to keep the base method at the same visibility level as its class, and "open up" the method in the subclass, as that will communicate intent more clearly:

abstract class Base {
    void x() {}
}

public class Sub extends Base {
    /** public Javadoc here */
    @Override
    public void x() {
        super.x();
    }
}

I don't see any reason why this approach should be applied to static methods as in your case.

2. The method must be public

... because it implements a method from an interface. Unfortunately, Java doesn't offer package-private or private interface methods. So the following is usual, even without any subclasses, and even if the interface itself might be package-private (or even nested private):

final class Y implements X {
    @Override
    public void x() {}
}

This (unfortunately) also applies to static classes on interfaces, which can only be public:

interface I {
    /* implicitly public */ static void x() {}
}
like image 98
Lukas Eder Avatar answered Oct 17 '22 08:10

Lukas Eder


There are two schools of thought on this:

One group prefers adding unnecessary modifiers (e.g. public in this case, private in private classes) as a form of "documentation in code". For example, this is the viewpoint Eric Lippert espouses in his answer on this related C# question.

The other group prefers to never add source code that has no functional effect: if public isn't doing anything then it doesn't belong in your source code.

I think I am now firmly in the second camp, but I understand the arguments from the first camp and I think it's not nearly as cut and dried as it might first appear. Reasonable people can disagree, which is why (like braces and whitespace) this is something you should decide once in a project style guide and then never debate again. :-)

like image 27
Daniel Pryden Avatar answered Oct 17 '22 09:10

Daniel Pryden