Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Thinking in Java
Prev Contents / Index Next

Inner classes and upcasting

So far, inner classes don’t seem that dramatic. After all, if it’s hiding you’re after, Java already has a perfectly good hiding mechanism—just give the class package access (visible only within a package) rather than creating it as an inner class.

However, inner classes really come into their own when you start upcasting to a base class, and in particular to an interface. (The effect of producing an interface reference from an object that implements it is essentially the same as upcasting to a base class.) That’s because the inner class—the implementation of the interface—can then be completely unseen and unavailable to anyone, which is convenient for hiding the implementation. All you get back is a reference to the base class or the interface.

First, the common interfaces will be defined in their own files so they can be used in all the examples:

//: c08:Destination.java
public interface Destination {
  String readLabel();
} ///:~


//: c08:Contents.java
public interface Contents {
  int value();
} ///:~


Now Contents and Destination represent interfaces available to the client programmer. (The interface, remember, automatically makes all of its members public.)

When you get back a reference to the base class or the interface, it’s possible that you can’t even find out the exact type, as shown here:

//: c08:TestParcel.java
// Returning a reference to an inner class.

class Parcel3 {
  private class PContents implements Contents {
    private int i = 11;
    public int value() { return i; }
  }
  protected class PDestination implements Destination {
    private String label;
    private PDestination(String whereTo) {
      label = whereTo;
    }
    public String readLabel() { return label; }
  }
  public Destination dest(String s) {
    return new PDestination(s);
  }
  public Contents cont() {
    return new PContents();
  }
}

public class TestParcel {
  public static void main(String[] args) {
    Parcel3 p = new Parcel3();
    Contents c = p.cont();
    Destination d = p.dest("Tanzania");
    // Illegal -- can't access private class:
    //! Parcel3.PContents pc = p.new PContents();
  }
} ///:~


In the example, main( ) must be in a separate class in order to demonstrate the privateness of the inner class PContents.

In Parcel3, something new has been added: The inner class PContents is private, so no one but Parcel3 can access it. PDestination is protected, so no one but Parcel3, classes in the same package (since protected also gives package access), and the inheritors of Parcel3 can access PDestination. This means that the client programmer has restricted knowledge and access to these members. In fact, you can’t even downcast to a private inner class (or a protected inner class unless you’re an inheritor), because you can’t access the name, as you can see in class TestParcel. Thus, the private inner class provides a way for the class designer to completely prevent any type-coding dependencies and to completely hide details about implementation. In addition, extension of an interface is useless from the client programmer’s perspective since the client programmer cannot access any additional methods that aren’t part of the public interface. This also provides an opportunity for the Java compiler to generate more efficient code.

Normal (non-inner) classes cannot be made private or protected; they may only be given public or package access.
Thinking in Java
Prev Contents / Index Next


 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire