25
class MyClass 
{
    public static final int num=90;
}
  • Why am I allowed to create a public member in a non-public class?
  • Is there another way of accessing this member that I do not know of (other than through the class name)?
XForCE07
  • 1,176
  • 1
  • 10
  • 10
  • Likewise, you can declare a method on an interface to be `public` and `abstract` even though those properties are both necessarily true anyway, and you can declare its arguments `final` even though it's meaningless in that context. Java is a strange beast. – Chris Martin Mar 03 '14 at 00:59
  • @fge I'm not sure that's true. `MyClass` may not be visible outside the package, but you could add a `public` class that extends it. Now the access modifiers on the members become really important, I think. – ajb Mar 03 '14 at 01:15
  • Related: http://stackoverflow.com/questions/6264657/why-make-private-inner-class-member-public-in-java?rq=1 – Jason C Mar 03 '14 at 01:43
  • 1
    @JasonC, the same technique that I used for static fields can also be used for member variables ("normal" fields). We should have more faith in the Java Grammar :). – Anthony Accioly Mar 03 '14 at 02:11

4 Answers4

18

Since your question was about members, I will address both fields and methods (non-static; Anthony Accioly's answer touches on another good use case, which also includes static fields).

While in many situations this is just an ambiguous consequence of the language's grammar (in particular: public fields in non-public classes, as in your example snippet), there are very good reasons for needing to be able to use public methods in non-public classes.

Expanding on Mik378's answer, consider, e.g., the following (contrived example):

import ...;

class BleebleAscendingComparator implements Comparator<Bleeble> {
    @Override public int compare (Bleeble o1, Bleeble o2) { ... }
}

class BleebleDescendingComparator implements Comparator<Bleeble> {
    @Override public int compare (Bleeble o1, Bleeble o2) { ... }
}

public class BleebleView {  
    public enum SortMode { ASC, DESC };
    public Comparator<Bleeble> getDisplayOrderComparator (SortMode mode) {
        if (mode == SortMode.ASC)
            return new BleebleAscendingComparator();
        else
            return new BleebleDescendingComparator();
    }
}

You cannot instantiate one of those Comparator implementations directly outside of that context, but they must override public methods of Comparator, and their functionality is accessible via a Comparator interface.

This same reasoning applies to, e.g., private or protected inner classes. If you were not able to declare methods public, you would have no way of overriding public methods of interfaces that they inherit or classes that they extends.

Practical Examples:

  • You use this every time you override a public method in an anonymous inner class (e.g. every time you override public void actionPerformed in an anonymous ActionListener).

  • Consider any non-public class that you would like to store in a HashMap. You would override the public equals() and hashCode() in that non-public class, and the implementation of HashMap can access them regardless of the fact that the class is non-public.

  • The often overridden public toString() is another common example of a public member of a potentially non-public class.

  • A more complex example is the use of java.sql.Driver in java.sql.DriverManager (in general, factory-type designs make heavy use of this concept) -- an SQL driver implementation may not make implementation classes public (e.g. the Oracle driver produces non-public Connection objects).

  • Many more... if you keep an eye out for examples of this, you'll be surprised how common it really is!

Community
  • 1
  • 1
Jason C
  • 38,729
  • 14
  • 126
  • 182
5

Don't forget that classes with default access can be subclassed by public classes in the same package.

package package1;

class MyDefaultClass {

    public static final int MY_CONSTANT = 0xCAFEBABE;
}

public class PublicExporter extends MyDefaultClass {

}

Now the public class acts as a bridge, and you are able to consume MyDefaultClass public members from other packages.

package package2;

import package1.PublicExporter;

public class Consumer {
    public static void main(String[] args) {
        System.out.printf("%x\n", PublicExporter.MY_CONSTANT);
    }
}

Consumers can even import static members:

import static package1.PublicExporter.MY_CONSTANT;

public class Consumer {
    public static void main(String[] args) {
        System.out.printf("%x\n", MY_CONSTANT);
    }
}
Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118
3

When a public method belonging to an enclosing class A returns a reference (public supertype reference, like an interface) to its inner class B having default scope, external client (outside A's package) can only call B's methods but can't CREATE themselves fresh instances of B.

If the B's methods weren't public, external client couldn't reach them, and worse: would cause a compilation error since not well implementing its interface.

This modeling could be useful in a certain context, to improve code design.

Mik378
  • 21,881
  • 15
  • 82
  • 180
  • How can external clients call these methods when they cannot see the class? How would they know about the method? – Thilo Mar 03 '14 at 00:49
  • Updated my answer. Just imagine the return type as being the `public` interface of the inner class. Assuming `inner class` with default scope so, extends this `interface` – Mik378 Mar 03 '14 at 00:52
  • How can a public method return a non-public class? What is the caller supposed to do with that? He can only treat is as `Object`. – Thilo Mar 03 '14 at 00:53
  • 1
    Okay, if you implement an interface, then it's a wholly different matter. But the question was about fields. – Thilo Mar 03 '14 at 00:54
  • @Thilo The inner class implementing an interface doesn't change the concept. – Mik378 Mar 03 '14 at 00:56
  • Well, an interface defines a collection of public methods for precisely this case: make it possible for calling code to call methods without having to know about the class that implements them. – Thilo Mar 03 '14 at 00:58
  • @Thilo `static final` is totally legal in an interface, since acting as a constant. It represents a case where an inner class having default scope requires a field as `public` => answering the OP. – Mik378 Mar 03 '14 at 01:00
  • `static` fields are not dynamically dispatched anyway. So you don't need to return an instance of your private class at all. – Thilo Mar 03 '14 at 01:04
  • @Thilo You may want to see the JasonC 's answer to figure out the idea. – Mik378 Mar 03 '14 at 01:21
0

When you declare a variable public it essentially becomes exactly that ; it's able to be seen throughout your entire program, without any special getters/setters. The class does not necessarily need to be public in order for its members to be public also.

Remember, in Java you can only have 1 public class per compilation unit( .java file), and that public class needs to have the same name as the compilation unit. Other than that, it doesn't "own" ownership of the keyword public.

The fact that you declared num as public and static allows you to say System.out.println(MyClass.num). The public attribute allows you to get the num variable directly. Thus, you do not have to create a method to return num for you. Because it is public, you can also say

      MyClass mc = new MyClass();
      System.out.println(mc.num);

However, since you also added the static declaration, you should only access it via the class name, i.e MyClass.num

Point to take home: public variables can exist in any type of class, and they allow you to access them without the need for getters and setters. Public classes, however, are not the only classes that can own public variables.

Alejandro
  • 3,040
  • 1
  • 21
  • 30
  • a class being public has nothing to do with the existence of a main method. – EasterBunnyBugSmasher Mar 03 '14 at 00:47
  • "The class does not necessarily need to be public in order for its members to be public also." Are you sure? The comment by @fge on the question suggests the opposite. – Thilo Mar 03 '14 at 00:51
  • @DirkHaase good point, I should edit that to say that the JVM will look at the public class for the existence of main – Alejandro Mar 03 '14 at 00:53
  • @Thilo, I am pretty sure. The code for the question is legal Java, isn't it? The members can be declared public, and within the same Java file the scope would be public – Alejandro Mar 03 '14 at 00:55
  • " That is all that a public class needs to have that differentiates it from any other class." A PUBLIC CLASS DOESN'T NEED A MAIN METHOD! – EasterBunnyBugSmasher Mar 03 '14 at 01:05
  • 2
    Ahh, I see where I've made my mistakes. Thanks for pointing that out – Alejandro Mar 03 '14 at 01:14
  • @Thilo The comment by fge on the question is incorrect. – Jason C Mar 03 '14 at 01:29
  • @AlejandroLucena *"public variables can exist in any type of class, and they allow you to access them without the need for getters and setters"* - This is not limited to public variables and is not a reason for declaring something `public`. Non-public members of non-public inner classes can be accessed by the enclosing class, for example, and default access members can be accessed anywhere in the package. This is kind of a misleading answer. – Jason C Mar 03 '14 at 04:07