Monthly Archives: January 2015

Calling grandparent methods in Java: you can not

In the article Fine points of protection I detailed how “protected” extends the “package private” access. There I wrote:

What you can do is

  • Override the method in the child class or
  • call the parents method using the keyword super.

And generally this is really all you can do with protected methods.

(Note that in this article I talk about methods and method calling, but the very similar statements can be said about fields, constructors.)

If you can call super.method() to access the parent’s method() even if the actual class has overridden it why can not you call super.super.method()?

The absolutely correct and short answer is: because Java language does not allow you to do that. (JVM does though, but you should not.) You can not directly access grandparent methods skipping parent methods. The interesting question is: Why?

The reason lies in object orientation principles. When you extend a class you extend the defined functionality of the class.

The fact that the parent class extends another class (the grandparent class) is part of the implementation that is none of the business of any other code outside of the class. This is the basic principle of encapsulation: advertise the defined functionality of a class to the outside world but keep the implementation private. There are secrets that you keep hidden even from your son. “Nicht vor dem Kind.”

Generally this is the reason. If you could access the grandparent directly you would create a dependency on the implementation of the father, and this would violate encapsulation.

Advertisement

Fine points of protection

In the article Some Sentences about Java I wrote that “Protected methods and fields can be used from
classes in the same package (so far the same as package private) and in addition to that it can be used from other classes that extend the class containing the protected field or method.”

Although the statement above is true it may not reveal the whole truth and I believe it deserves a new article.

When you have a private X (method, field, class, interface, constructor) in a class you can use that X from within the top level class. The use means, as described in the previous article, that X can be accessed in the instance “this” and in other instances so long as long the code accessing is in the same top level class where X is.

If you remove the private keyword in front of X then you extend the visibility to package level. You can use X inside the package the same way as you could use it before from within the class when it was private.

If we still go further one step and insert the keyword protected in front of X it will became visible from classes that extend the class where X is declared but can NOT be accessed the SAME WAY as private X from within the class or package private from within the same package. Since protected is extending the visibility of X from package private, protected X can still be used the same way within the package, but not the same way outside of it.

The difference is that you can only access a protected X in the code that is extending the functionality of X.

The above is not a precise definition. The Java Language Specification that I cite here in this blog many times details that in chapter 6.6.2 What can I say about that? Precise, complete but may not be easy or entertaining to read, which may also be true for this article, but since you are reading it I assume that you find it entertaining, educating or you have some very specific reason to read it.

While you are in the same package as the class declaring X you can access X on other instances. We can have some simple classes to demonstrate this. First of all we can have a root class that we will extend:

package a;
public class A {
	protected void protectedMethod(A a) { }
}

We have the class ‘B’ which extends ‘A’ and is in the same package.

package a;
import a.A;
public class B extends A {
	@Override
	protected void protectedMethod(A a) {
		a.protectedMethod(this);
		super.protectedMethod(this);
	}
}

If we move/copy the class ‘B’ to another package, like here:

package b;
import a.A;
public class B extends A {
	@Override
	protected void protectedMethod(A a) {
		a.protectedMethod(this);
		super.protectedMethod(this);
	}
}

then the line 6 will not compile. When it was in the previous package the compiler allowed it to access the method, because package protection made it possible. No matter what implementation instance the argument ‘a’ is to the method, they are in the same package. In case of ‘b.B’ class package protection does not allow access and because the actual object instance that we store in the method argument ‘a’ may be an instance of a class that ‘b.B’ is not extending it can not access it. It can be an instance for example of the class:

package c;
import a.A;
public class C extends A { }

What you can do is

  • Override the method in the child class or
  • call the parents method using the keyword super.

And generally this is really all you can do with protected methods outside of their package.

Use copy paste programming!

Copy paste is bad

We hate copy paste. Why? Because the result code is unmaintainable. I get a bug reported from QA, I analyze the code, look at logs, debug, drink a lot of coffee and finally I get to the code that is the root cause of the bug. I fix it, test the use case, release new code to learn next day that a very similar bug appears in a similar use case. In that case a different code runs looking very similar to the one I was mending the day before and I just start to wonder how many more copies of the same code will I face and have to change.

There are things worse than copy paste

Now imagine a schnitt, like in movies. Let’s jump to another time. I get a bug reported from QA, I analyze the code. I do not understand. There are a lot of small interfaces, abstract classes, deep hierarchies. Many of the classes have no direct relation to business. I ask for help from the developer who created the code, and he starts to explain. In two days I start to understand his idea of coding structure and how he was implementing the code in a strict object oriented way, avoiding the slightest copy/paste. After three days I find the place where a single line has to be modified. Before doing that I plan to create the unit test to fail first, then fix the code and re-run the unit test to see that the same error never comes again. So I open the unit test class testing the one I am going to modify and I do not understand how it works. It is complex and extends another class that uses another and another. This time it is a bit easier to understand since I already know the mindset of the programmer, who created it but it is still a whole day to create the new test. We are already in day #4 following the bug report customers banging on the door for fix.

To copy or not to copy…

Which is the better approach? Have some copy paste and face that some of the bugs will just appear in other areas or have an extremely strict but deep hierarchy OO design in the code that avoids bug reappearing but has a steep learning curve?

There is no one and only one best ever answer for this question. Neither of them is a good approach. Sometimes some copy paste may be forgivable sin. Deep inheritance structure is difficult to understand. It is usually recommended not to have more than three levels. One may also argue that in the above example the code could have been created with less levels of inheritance without actual copy paste. (Except that the above is not an actual but an imagined example distilled from many years of experience.) The level of repetition may conflict with OO structure. When you have the OO structure you make abstraction. Abstract code is harder to understand. When you copy-paste-modify the modified code will be on the same abstraction level as the one you copied. It may be easier to understand.

Copy unit test code

When it is about unit tests, I tend to forgive copy paste and verbosity to get simpler structures and readability. But that is because unit tests are more documentation than code. They have to be expressive as you look at it immediately. It should not require investigation and understanding of code structures defined somewhere else to get the point what the test is doing. I tend to agree with a unit test that copies one test and then contains slightly modified code. It still has one of the drawbacks on maintenance: if you change the code the change has to be propagated to all other places as well where the code was copied. But in this case if you forget to propagate the change you will get test errors or failures. This way you can see copy paste as an advantage: when you change the code you are forced to look at, refactor and think through all the test cases that are affected.

Do not copy production code

These effects that turn drawbacks to advantages in case unit test code may become a nightmare in production code. If you have doubt then do not copy. Do not be afraid to create too steep hierarchy structure. Programmers fall more often into the copy-paste trap than into steep hierarchies. Unless you are a senior programmer I recommend that you avoid copy-paste in production code at all costs as a rule of thumb. If you are senior you do not need my recommendation: you will avoid copy-paste on your own.

Side note

Just a story: Some time ago I wrote some mail about copy-paste in a code and I created a typo writing copy-pasta. In a few minutes I got a reply: “Pasta? You are referring to spaghetti code?” Nomen est omen.

Some more sentences on Java, private variables

In the article Some Sentences about Java I described that privates variables are visible from inner and nested classes and the other way around also. This is done on Java level, it is a feature of the language. However knowing that the JVM does not know anything about inner and nested classes one may wonder how this is implemented.

No inner classes in JVM

When you compile a Java class source file the compiler generates the binary file with the extension .class from the .java file. This binary file contains the symbolic information needed by the compiler to compile other classes that some way depend on this class and it also contains the JVM byte code, which is needed to execute the program. The same is true for interfaces except that they contain executable code only for default methods and for field initialization code executed when the classloader loads the interface.

When there is a class inside another class or interface then the compiler generates extra .class files for these classes. The name of these classes usually contain the name of the outer class, $ sign and the name of the inner or nested class. Since the $ sign is a legal character in an identifier in Java the JVM can not tell, and does not bother to tell if the class is an inner or top level class in Java language level.

Private is not private then?

Private methods and fields this way are accessed between classes. Because JVM does not know class nesting these are, for the JVM, “top level” classes.

As a sample lets have a Java code:

package com.javax0;
public class Inner {
	private static class InnerInner {
		private static Object b;
	}
	public void m() {
		InnerInner.b = null;
	}
}

If I compile the code with the command line

$ javac  Inner.java
$ ls -1
Inner$InnerInner.class
Inner.class
Inner.java

I get the two class files. Dissassembling the inner class:

$ javap -v Inner\$InnerInner.class 
Classfile /Users/verhasp/github/JavaBeanTester/src/test/java/com/javax0/Inner$InnerInner.class
  Last modified 2014.12.27.; size 413 bytes
  MD5 checksum 79f4ea55abe8211fec751d9a4dec9ae1
  Compiled from "Inner.java"
class com.javax0.Inner$InnerInner
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Fieldref           #3.#15         // com/javax0/Inner$InnerInner.b:Ljava/lang/Object;
   #2 = Methodref          #4.#16         // java/lang/Object."<init>":()V
   #3 = Class              #18            // com/javax0/Inner$InnerInner
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               b
   #6 = Utf8               Ljava/lang/Object;
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               access$002
  #12 = Utf8               (Ljava/lang/Object;)Ljava/lang/Object;
  #13 = Utf8               SourceFile
  #14 = Utf8               Inner.java
  #15 = NameAndType        #5:#6          // b:Ljava/lang/Object;
  #16 = NameAndType        #7:#8          // "<init>":()V
  #17 = Class              #22            // com/javax0/Inner
  #18 = Utf8               com/javax0/Inner$InnerInner
  #19 = Utf8               InnerInner
  #20 = Utf8               InnerClasses
  #21 = Utf8               java/lang/Object
  #22 = Utf8               com/javax0/Inner
{
  static java.lang.Object access$002(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
    flags: ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: dup
         2: putstatic     #1                  // Field b:Ljava/lang/Object;
         5: areturn
      LineNumberTable:
        line 4: 0
}
SourceFile: "Inner.java"
$ 

you can notice that an synthetic method was created to set the value of the private field b. This method is needed to access the field from the outer class. The direct access is prohibited by the JVM but the compiler allows you to access the field through the synthetic methods it generates. You can not, however call the synthetic method from any other class, because the Java compiler will refuse to compile the code that tries to access directly a synthetic method. This protection works on the compiler level. If you happen to craft some JVM code directly using some special tool that accesses the synthetic method, the JVM will not stop you.

Eclipse warnings

There is another sign that you may face when creating classes causes the compiler to create synthetic methods. This is when Eclipse warns you about it:

Fullscreen_2014__12__27__19_00

This screen capture shows the line #7 of the previous Java source code where Eclipse tells you that though the code “InnerInner.b = null;” looks like a simple assignment it will be executed as a method call.

Fortunately you can configure Eclipse not to display this warning.

Synthetic methods

If you are interested more in synthetic and bridge methods, read a previous article of Java Deep.

Should we avoid private variables inside inner classes?

The final question after we looked at this detail of the Java language is how seriously we should be worried about the warning that Eclipse gives us. Should we use private nested classes or should we avoid them?

If we use them then the generated JVM code will be littered with synthetic methods and thus the execution will be more complex. If we do not use them then the generated JVM code will be simpler. Should I be worried about the simplicity and the coolness of the generated JVM? I doubt.

What I would focus on is the readability of the code we maintain and not the code javac generates.