Question

It item no 74 of effective java book there is a paragraph (2nd para from last of the item 74) which mentions as per below:

Inner classes (Item 22) should not implement Serializable. They use compiler-generated synthetic fields to store references to enclosing instances and to store values of local variables from enclosing scopes. How these fields correspond to the class definition is unspecified, as are the names of anonymous and local classes. Therefore, the default serialized form of an inner class is ill- defined.

I know about inner class uses compiler generated synthetic field to store reference to enclosing instances e.g. if the enclosing class is MyEnclosing and inner class is MyInner then the enclosing reference is MyEnclosing.this. But i am not able to get the BOLD part. Please help me getting the meaning. Thanks!!!

Was it helpful?

Solution

Suppose you have a local class like this:

 class OuterClass {
    Runnable run;

    void method() {
       final int a = 8;
       this.run = new Runnable() {
          public void run() {
             System.out.println(a);
          }
       };
    }
 }

Now suppose I try to serialize this, which contains an object of this inner class type. My compiler names that class OuterClass$1 and gives it a field called val$a. But the exact names to be used in this situation are not part of the compiler's spec. Another compiler might choose to call the inner class OuterClass$method$1. In that case, serializing in one compiled version and deserializing in the other would fail, even though the same source file was used.

(Plus, there's also the problem that an anonymous inner class does not have a no-args constructor. But due to the problem above, even a named inner class cannot reliably serialize)

OTHER TIPS

Consider the following code:

public class Main {
    public static void main(String[] args) {
        final int x = Integer.valueOf(args[0]);
        new Object() {
            void print() {
                System.out.println(x);
            }
        }.print();
    }
}

My compiler calls the anonymous inner class Main$1. When I disassemble it, I see that a copy of the value of x from the outer scope is stored in a private field called val$x:

private final int val$x;

This is an example of what the bold part is talking about.

An inner class is a non-static class defined within some other class:

class Outer implements Serializable {
    private String someString;

    class Inner implements Serializable {
        private int someInt;
    }

}

Once you have an instance of the Inner class, when you serialize it, it must have a reference to the outer class (which it accesses internally via the Outer.this reference) and how this is achieved for a serialized object is unspecified. The same applies to a local class:

class Outer implements Serializable {
    private String someString;

    Serializable method(final int i) {
        class Inner implements Serializable {
            Inner() {
                System.out.println(i);
            }
        }
        return new Inner();
    }
}

If you serialize the value returned by method(), it would need to have a reference to i, but that's not reliable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top