Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

What Is Private in Java 9?

DZone's Guide to

What Is Private in Java 9?

Let's take a deep dive into the private access modifier, how the JVM interprets it, and what changes Java 9 will bring to it that you should keep an eye on.

· Java Zone
Free Resource

Are you joining the containers revolution? Start leveraging container management using Platform9's ultimate guide to Kubernetes deployment.

When doing interviews, I experience that most of the candidates do not know what private modifier in Java really means. They know something about it that is enough for everyday coding, but the knowledge is usually far from complete. It is not a problem. Knowing enough is, well… enough. But it is still interesting to know some of the inner workings of Java. In some rare cases, it may shed light on some details. If nothing else, it is entertaining .orElse(whyDoYouReadIt)?

By the way: Mentioning interviews is a good opportunity to write rants even if the statements and implications related to my person are, in my view, false. After all, my person is not important, and distancing myself from the fact that it criticizes me, I find the article interesting. That way, the conclusions about the interviews are important and, I may find, are actually totally in line with my opinion.

This article is to describe some Java facts, hopefully in a bit more readable way than reading the language standard.

So, What Is Private?

private is an access modifier in Java. If you have a private member (method, field, inner, or nested class or a nested interface) of a class, it can only be used by code that is in the same class. The interesting question is: What happens when there is more than one class that the private method is in? How can it be in more than one class? In case there is a class that contains another class and there is a private method inside the inner/nested class, then it is inside the inner/nested class and also in the top level class.

Can a private method inside an enclosed class be called from the outer class? Can code inside an enclosed class call a private method in the outer class? The answer is yes in both cases. The sample code...

package javax0.package1;

class TopLevelClass {

    void topMethod() {
        NestedClass nc = new NestedClass();
        nc.method();
    }

    private int z;

    interface NestedInterface {
        default void method() {
            TopLevelClass tlc = new TopLevelClass();
            tlc.z++;
        }
    }

    static class NestedClass {
        private int k;

        private void method() {
            TopLevelClass tlc = new TopLevelClass();
            k = tlc.z;
        }
    }
}


...clearly shows this situation: The nested class NestedClass and the nested interface NestedInterface both contain code that can access the outer class contained private field z. Similarly, the top level class code can call the private method inside the nested class. The fact that this sample code does not actually perform anything reasonable is not important in this case.

If we compile this single source file, we get three class files:

  1. TopLevelClass$NestedClass.class
  2. TopLevelClass$NestedInterface.class
  3. TopLevelClass.class

That is because the JVM does not know what the top level is and what is nested. The JVM does not know anything about nested and top level classes. For the JVM, a class is just a class. A top level class if you insist. That is mainly because the Java language 1.0 did not have nested and inner classes, and the JVM was designed according to that. When inner and nested classes were introduced in Java 1.1, the compilation was modified — but only so that the inner and nested classes remained language features that were not handled by the JVM directly.

How can the top level class access a private method in another class that was nested in the source code, but when it is compiled, it is just another “top level” class? They are on the same level. If the accessibility were changed to public, then we could also access it from other classes, but we cannot. The compiler will not allow any other code in other classes to access the private method, and even if we did some trick to overcome the compiler, the generated class file will make the JVM throw an exception. Private in Java is private.

What really happens is that the compiler generates special getter and setter methods to get access to field z.

Such a bridge method is created for every private field or method that is accessed from a different class inside the same top level class. If the private whatever is not accessed from the enclosing class, then the method is not generated. If the field is only read, then only the getter is generated. If it is only set from outside, then only the setter is generated.

This is also an interesting failure — believing that a private field (or whatever) is accessible only from within the same object. That is the usual way we use these members when we program, but if the code has a reference to another instance of the same type, then through that reference, we can access the private fields of the other object just as well as we can access “our own” fields. Is this a rare case? You may think so because you rarely program it. But in reality, it is extremely frequent: The IDE usually generates the code for us, and that is why some developers do not think about that. Without this, it would hardly be possible to code the equals(Object other) method of classes.

What About Java 9?

So far, there is nothing specific to Java 9 in this article, and these days, every Java article should be about Java 9 (or 10 already?).

If we look at access control, generally we have to talk about JPMS, and there are many great articles about that. codeFx has a good list of articles about it. Stephen Colebourne has nice articles, too.

Soon you will be even able to buy books about Java module systems from different publishers. I am in a lucky position that I can already read one in a draft from Packt as a reviewer and I love it. But JPMS does not change “private” on this level. Still, there will be nested classes and inner classes and bridge methods — exactly the same as before.

The little difference is that Java 9 now has private methods inside interfaces. This means that now we should be prepared to have synthetic bridge methods — not only in inner and nested classes, but also in interfaces.

Takeaway

Sometimes, the simplest things are not as simple as they seem. After all, all of IT is nothing but a bunch of 0s and 1s. It is just that we have a lot of them. Really a lot. If there was something new to you in this article, then it should tell you that there are areas in the Java language and the JVM that you may be interested in examining a bit more. For example:

  • What is the difference between a nested and an inner class?
  • Can you have a nested interface inside a class, and similarly, can you have an inner interface inside a class?
  • What about classes or interfaces inside an interface? Can you have an inner class in an interface? How about a nested class?
  • Can you write code using reflection that lists all the methods a class has? Will it list the synthetic methods? What modifiers will it have?
  • When you compile an inner class, it will have the compiled name Outer$Inner.class, which is a legitimate name. But what happens if there is an Outer$Inner.java source file? Figure it out!
  • The generated synthetic methods also have legitimate names. What happens if you define a method with that name? Is it Java specification or implementation specific that you see?
  • How deep can you nest inner and nested classes and/or interfaces? Can a nested class contain an inner class? Can an inner class contain a nested class?
  • What is your guess as to why there is no symbolic name in the JDK for the synthetic modifier? Why can the actual modifier value be the same as the value for volatile fields?
  • Can you have a static field, class, or method inside a nested class?

The answer to those questions and the knowledge is not practical, I know. I have never ever seen any code or project where knowing that an inner class cannot have a static field was to any advantage. On the other hand, thinking about these and getting the answers may give you some joy, like solving crosswords — if that is your taste. It's also knowledge that still may be useful in aiding the understanding the technology in a way that we do not recognize. In some situations, one person just finds a bug faster than others because they “feel” the technology. That is when you cannot tell what was whispering the solution into your ears — but something, knowledge like the above, did. But it will only whisper to you if you love to dig into those fine bits of the technology.

Last a trick question, even less practical than those above — just for entertainment, if you like:

Puzzle

We know that it is not possible to have a static field inside an inner (not nested) class. Is it still possible to have a compiled class file generated by the Java compiler from an inner class that has a static method?

Moving towards a private or Hybrid cloud infrastructure model? Get started with our OpenStack Deployment Models guide to learn the proper deployment model for your organization.

Topics:
java ,private ,nested classes ,java 9 ,tutorial

Published at DZone with permission of Peter Verhas, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}