Showing posts with label Inner Class. Show all posts
Showing posts with label Inner Class. Show all posts

Saturday, 30 April 2011

Inner Class Nested Levels In Java

How frequently does one see inner classes being used in an application leave aside inner classes at nested levels.
Yes one can have as many nested level of inner classes . The code below proves it.

However, the usability of this code is debatable.

public class Test{
    class a1{
        class a2{
            class a3{
                class a4{
                }
            }
        }
    }
   public static void main(String[] args) {
       Test.a1.a2.a3.a4 abc = new Test().new a1().new a3().new a4().new a6();
    }
}

Tuesday, 19 April 2011

Scope and inner-ness of nested class

Following table shows various nested classes:
Types of Nested Classes
Type Scope Inner
static nested class member no
inner [non-static] class member yes
local class local yes
anonymous class only the point where it is defined yes

Sunday, 20 February 2011

How Inner Classes Work in java


The preceding sections have explained the features and behavior of the various types of inner classes. Strictly speaking, that should be all you need to know about inner classes. In practice, however, some programmers find it easier to understand the details of inner classes if they understand how they are implemented.
Inner classes were introduced in Java 1.1. Despite the dramatic changes to the Java language, the introduction of inner classes did not change the Java Virtual Machine or the Java class file format. As far as the Java interpreter is concerned, there is no such thing as an inner class: all classes are normal top-level classes. In order to make an inner class behave as if it is actually defined inside another class, the Java compiler ends up inserting hidden fields, methods, and constructor arguments into the classes it generates. You may want to use the javap disassembler to disassemble some of the class files for inner classes so you can see what tricks the compiler has used to make inner classes work. (See Chapter 8, "Java Development Tools", for information on javap.)

3.13.1. Static Member Class Implementation

Recall our first LinkedStack example (Example 3-8), which defined a static member interface named Linkable. When you compile this LinkedStack class, the compiler actually generates two class files. The first one is LinkedStack.class, as expected. The second class file, however, is calledLinkedStack$Linkable.class. The $ in this name is automatically inserted by the Java compiler. This second class file contains the implementation of the static member interface.
As we discussed earlier, a static member class can access all the static members of its containing class. If a static member class does this, the compiler automatically qualifies the member access expression with the name of the containing class. A static member class is even allowed to access the privatestaticfields of its containing class. Since the static member class is compiled into an ordinary top-level class, however, there is no way it can directly access theprivate members of its container. Therefore, if a static member class uses a private member of its containing class (or vice versa), the compiler automatically generates non-private access methods and converts the expressions that access the private members into expressions that access these specially generated methods. These methods are given the default package access, which is sufficient, as the member class and its containing class are guaranteed to be in the same package.

3.13.2. Member Class Implementation

A member class is implemented much like a static member class. It is compiled into a separate top-level class file, and the compiler performs various code manipulations to make interclass member access work correctly.
The most significant difference between a member class and a static member class is that each instance of a member class is associated with an instance of the enclosing class. The compiler enforces this association by defining a synthetic field named this$0 in each member class. This field is used to hold a reference to the enclosing instance. Every member class constructor is given an extra parameter that initializes this field. Every time a member class constructor is invoked, the compiler automatically passes a reference to the enclosing class for this extra parameter.
As we've seen, a member class, like any member of a class, can be declared publicprotected, or private, or given the default package visibility. However, as I mentioned earlier, there have been no changes to the Java Virtual Machine to support member classes. Member classes are compiled to class files just like top-level classes, but top-level classes can only have public or package access. Therefore, as far as the Java interpreter is concerned, member classes can only have public or package visibility. This means that a member class declared protected is actually treated as a public class, and a member class declaredprivate actually has package visibility. This does not mean you should never declare a member class as protected or private. Although the interpreter cannot enforce these access control modifiers, the modifiers are noted in the class file. This allows any conforming Java compiler to enforce the access modifiers and prevent the member classes from being accessed in unintended ways.

3.13.3. Local and Anonymous Class Implementation

A local class is able to refer to fields and methods in its containing class for exactly the same reason that a member class can; it is passed a hidden reference to the containing class in its constructor and saves that reference away in a private field added by the compiler. Also, like member classes, local classes can useprivate fields and methods of their containing class because the compiler inserts any required accessor methods.
What makes local classes different from member classes is that they have the ability to refer to local variables in the scope that defines them. The crucial restriction on this ability, however, is that local classes can only reference local variables and parameters that are declared final. The reason for this restriction becomes apparent from the implementation. A local class can use local variables because the compiler automatically gives the class a private instance field to hold a copy of each local variable the class uses. The compiler also adds hidden parameters to each local class constructor to initialize these automatically created privatefields. Thus, a local class does not actually access local variables, but merely its own private copies of them. The only way this can work correctly is if the local variables are declared final, so that they are guaranteed not to change. With this guarantee, the local class can be assured that its internal copies of the variables are always in sync with the real local variables.
Since anonymous classes have no names, you may wonder what the class files that represent them are named. This is an implementation detail, but the Java compiler from Sun uses numbers to provide anonymous class names. If you compile the example shown in Example 3-11, you'll find that it produces a file with a name like LinkedStack$1.class. This is the class file for the anonymous class.

Anonymous Classes

An anonymous class is a local class without a name. An anonymous class is defined and instantiated in a single succinct expression using the new operator. While a local class definition is a statement in a block of Java code, an anonymous class definition is an expression, which means that it can be included as part of a larger expression, such as a method call. When a local class is used only once, consider using anonymous class syntax, which places the definition and use of the class in exactly the same place.


Example of anonymous inner class
public static void main(String[] args) {
System.out.println("Value of X: " + X);

// create anonymous inner class
new Base("Y") {
{
System.out.println("Initializer block serves as constructor");
System.out.println("Value of b from Base: " + getB());
}

public void init() {
System.out.println("Value of X: " + X);
}
}.init(); // call init immediately after construction
}


An Enumeration Implemented with an Anonymous Class

public java.util.Enumeration enumerate() {

// The anonymous class is defined as part of the return statement

return new java.util.Enumeration() {

Linkable current; = head;
// Replace constructor with an instance initializer
{ current = head; }

public boolean hasMoreElements() { return (current != null); }

public Object nextElement() {

if (current == null)
throw new java.util.NoSuchElementException();

Object value = current;
current = current.getNext();
return value;
}

}; // Note the required semicolon: it terminates the return statement

}

One common use for an anonymous class is to provide a simple implementation of an adapter class. An adapter class is one that defines code that is invoked by some other object. Take, for example, the list() method of the java.io.File class. This method lists the files in a directory. Before it returns the list, though, it passes the name of each file to a FilenameFilter object you must supply. This FilenameFilter object accepts or rejects each file. When you implement the FilenameFilter interface, you are defining an adapter class for use with the File.list() method. Since the body of such a class is typically quite short, it is easy to define an adapter class as an anonymous class. Here's how you can define a FilenameFilter class to list only those files whose names end with .java:

File f = new File("/src");      // The directory to list

// Now call the list() method with a single FilenameFilter argument
// Define and instantiate an anonymous implementation of FilenameFilter
// as part of the method invocation expression.

String[] filelist = f.list(
new FilenameFilter() {

public boolean accept(File f, String s)
{
return s.endsWith(".java");
}

}); // Don't forget the parenthesis
//and semicolon that end the method call!



As you can see, the syntax for defining an anonymous class and creating an instance of that class uses the new keyword, followed by the name of a class and a class body definition in curly braces. If the name following the new keyword is the name of a class, the anonymous class is a subclass of the named class. If the name following new specifies an interface, as in the two previous examples, the anonymous class implements that interface and extends Object. The syntax does not include any way to specify an extends clause, an implements clause, or a name for the class.

Because an anonymous class has no name, it is not possible to define a constructor for it within the class body. This is one of the basic restrictions on anonymous classes. Any arguments you specify between the parentheses following the superclass name in an anonymous class definition are implicitly passed to the superclass constructor. Anonymous classes are commonly used to subclass simple classes that do not take any constructor arguments, so the parentheses in the anonymous class definition syntax are often empty. In the previous examples, each anonymous class implemented an interface and extended Object. Since the Object()constructor takes no arguments, the parentheses were empty in those examples.

Features of Anonymous Classes

One of the most elegant things about anonymous classes is that they allow you to define a one-shot class exactly where it is needed. In addition, anonymous classes have a succinct syntax that reduces clutter in your code.

Restrictions on Anonymous Classes

Because an anonymous class is just a type of local class, anonymous classes and local classes share the same restrictions. An anonymous class cannot define anystatic fields, methods, or classes, except for staticfinal constants. Interfaces cannot be defined anonymously, since there is no way to implement an interface without a name. Also, like local classes, anonymous classes cannot be public, private, protected, or static.

Since an anonymous class has no name, it is not possible to define a constructor for an anonymous class. If your class requires a constructor, you must use a local class instead. However, you can often use an instance initializer as a substitute for a constructor. In fact, instance initializers were introduced into the language for this very purpose.

The syntax for defining an anonymous class combines definition with instantiation. Thus, using an anonymous class instead of a local class is not appropriate if you need to create more than a single instance of the class each time the containing block is executed.


New Syntax for Anonymous Classes


new class-name ( [ argument-list ] ) { class-body }

or:

new interface-name () { class-body }
We've already seen examples of the syntax for defining and instantiating an anonymous class. We can express that syntax more formally as:

As I already mentioned, instance initializers are another specialized piece of Java syntax that was introduced to support anonymous classes. As we discussed earlier in the chapter, an instance initializer is a block of initialization code contained within curly braces inside a class definition. The contents of an instance initializer for a class are automatically inserted into all constructors for the class, including any automatically created default constructor. An anonymous class cannot define a constructor, so it gets a default constructor. By using an instance initializer, you can get around the fact that you cannot define a constructor for an anonymous class.


When to Use an Anonymous Class


As we've discussed, an anonymous class behaves just like a local class and is distinguished from a local class merely in the syntax used to define and instantiate it. In your own code, when you have to choose between using an anonymous class and a local class, the decision often comes down to a matter of style. You should use whichever syntax makes your code clearer. In general, you should consider using an anonymous class instead of a local class if:

  • The class has a very short body.

  • Only one instance of the class is needed.

  • The class is used right after it is defined.

  • The name of the class does not make your code any easier to understand.

Anonymous Class Indentation and Formatting

The common indentation and formatting conventions we are familiar with for block-structured languages like Java and C begin to break down somewhat once we start placing anonymous class definitions within arbitrary expressions. Based on their experience with inner classes, the engineers at Sun recommend the following formatting rules:

  • The opening curly brace should not be on a line by itself; instead, it should follow the close parenthesis of the new operator. Similarly, the new operator should, when possible, appear on the same line as the assignment or other expression of which it is a part.

  • The body of the anonymous class should be indented relative to the beginning of the line that contains the new keyword.

  • The closing curly brace of an anonymous class should not be on a line by itself either; it should be followed by whatever tokens are required by the rest of the expression. Often this is a semicolon or a close parenthesis followed by a semicolon. This extra punctuation serves as a flag to the reader that this is not just an ordinary block of code and makes it easier to understand anonymous classes in a code listing.

Local Classes

A local class is declared locally within a block of Java code, rather than as a member of a class.

Typically, a local class is defined within a method, but it can also be defined within a static initializer or instance initializer of a class. Because all blocks of Java code appear within class definitions, all local classes are nested within containing classes. For this reason, local classes share many of the features of member classes. It is usually more appropriate, however, to think of them as an entirely separate kind of inner class.
A local class has approximately the same relationship to a member class as a local variable has to an instance variable of a class.The defining characteristic of a local class is that it is local to a block of code. Like a local variable, a local class is valid only within the scope defined by its enclosing block.

Defining and Using a Local Class
// This method creates and returns an Enumeration object

public java.util.Enumeration enumerate() {
// Here's the definition of Enumerator as a local class
class Enumerator implements java.util.Enumeration {

Linkable current;
public Enumerator() { current = head; }
public boolean hasMoreElements() {
return (current != null);
}

public Object nextElement() {
if (current == null)
throw new java.util.NoSuchElementException();

Object value = current;
current = current.getNext();

return value;

}

}

// Now return an instance of the Enumerator class
//defined directly above
return new Enumerator();
}


Features of Local Classes
Local classes have the following interesting features:

  • Like member classes, local classes are associated with a containing instance, and can access any members, including private members, of the containing class.

  • In addition to accessing fields defined by the containing class, local classes can access any local variables, method parameters, or exception parameters that are in the scope of the local method definition and declared final.

Restrictions on Local Classes
Local classes are subject to the following restrictions:
  • A local class is visible only within the block that defines it; it can never be used outside that block.

  • Local classes cannot be declared public, protected, private, or static. These modifiers are for members of classes; they are not allowed with local variable declarations or local class declarations.

  • Like member classes, and for the same reasons, local classes cannot contain static fields, methods, or classes. The only exception is for constants that are declared both static and final.

  • Interfaces cannot be defined locally.

  • A local class, like a member class, cannot have the same name as any of its enclosing classes.

  • As noted earlier, a local class can use the local variables, method parameters, and even exception parameters that are in its scope, but only if those variables or parameters are declared final. This is because the lifetime of an instance of a local class can be much longer than the execution of the method in which the class is defined. For this reason, a local class must have a private internal copy of all local variables it uses (these copies are automatically generated by the compiler). The only way to ensure that the local variable and the private copy are always the same is to insist that the local variable is final.

New Syntax for Local Classes
In Java 1.0, only fields, methods, and classes can be declared final. The addition of local classes in Java 1.1 has required a liberalization in the use of the final modifier. It can now be applied to local variables, method parameters, and even the exception parameter of a catch statement. The meaning of the final modifier remains the same in these new uses: once the local variable or parameter has been assigned a value, that value cannot be changed.
Instances of local classes, like instances of member classes, have an enclosing instance that is implicitly passed to all constructors of the local class. Local classes can use the same this syntax as member classes, to refer explicitly to members of enclosing classes. Because local classes are never visible outside the blocks that define them, however, there is never a need to use the new and super syntax used by member classes to specify the enclosing instance explicitly.

Scope of a Local Class
In discussing member classes, we saw that a member class can access any members inherited from superclasses and any members defined by its containing classes. The same is true for local classes, but local classes can also access final local variables and parameters. The following code illustrates the many fields and variables that may be accessible to a local class:

class A { protected char a = 'a'; }
class B { protected char b = 'b'; }

public class C extends A {
// Private fields visible to local class
private char c = 'c';
public static char d = 'd';

public void createLocalObject(final char e)
{

final char f = 'f';
// i not final; not usable by local class
int i = 0;

class Local extends B
{

char g = 'g';
public void printVars()
{

// All of these fields and variables are accessible
//to this class

// (this.g) g is a field of this class
System.out.println(g);
// f is a final local variable
System.out.println(f);
// e is a final local parameter
System.out.println(e);
// (C.this.d) d -- field of containing class
System.out.println(d);
// (C.this.c) c -- field of containing class
System.out.println(c);
// b is inherited by this class
System.out.println(b);
// a is inherited by the containing class
System.out.println(a);

}

}

Local l = new Local(); // Create an instance of the local class
l.printVars(); // and call its printVars() method.

}

}


Local Classes and Local Variable Scope
A local variable is defined within a block of code, which defines its scope. A local variable ceases to exist outside of its scope. Java is a lexically scopedlanguage, which means that its concept of scope has to do with the way the source code is written. Any code within the curly braces that define the boundaries of a block can use local variables defined in that block.


Lexical scoping simply defines a segment of source code within which a variable can be used. It is common, however, to think of a scope as a temporal scope--to think of a local variable as existing from the time the Java interpreter begins executing the block until the time the interpreter exits the block. This is usually a reasonable way to think about local variables and their scope.
The introduction of local classes confuses the picture, however, because local classes can use local variables, and instances of a local class can have a lifetime much longer than the time it takes the interpreter to execute the block of code. In other words, if you create an instance of a local class, the instance does not automatically go away when the interpreter finishes executing the block that defines the class, as shown in the following code:
public class Weird {

// A static member interface used below

public static interface IntHolder { public int getValue(); }

public static void main(String[] args) {

// An array to hold 10 objects
IntHolder[] holders = new IntHolder[10];

for(int i = 0; i < 10; i++) { // Loop to fill the array up
final int fi = i; // A final local variable
// A local class
class MyIntHolder implements IntHolder {

public int getValue() { return fi; } // It uses the final variable

}

holders[i] = new MyIntHolder(); // Instantiate the local class

}

// The local class is now out of scope, so we can't use it. But
// we've got ten valid instances of that class in our array. The
//local variable fi is not in our scope here, but it is still
//in scope for the getValue() method of each of those ten objects.
//So call getValue() for each object and print it out.
//This prints the digits 0 to 9.

for(int i = 0; i < 10; i++)
System.out.println(holders[i].getValue());

}

}

The behavior of the previous program is pretty surprising. To make sense of it, remember that the lexical scope of the methods of a local class has nothing to do with when the interpreter enters and exits the block of code that defines the local class. Here's another way to think about it: each instance of a local class has an automatically created private copy of each of the final local variables it uses, so, in effect, it has its own private copy of the scope that existed when it was created.

Type of nested classes

A nested class is a class defined within another class. A nested classes should exist only to serve its enclosing class. If a nested class would be useful in some other context, then it should be a top-level class. This was covered in the post : Nesting of classes : Introduction.

Note : Inner classes are one type of nested class. So both cannot be inter-changeably used.

Types of nested class : Introduction
There are two types of nested classes: static and non-static.

A static nested class is one which has the static modifier applied. Because it is static, it must access the members of its enclosing class through an object. That is, it cannot refer to members of its enclosing class directly. Because of this restriction, static nested classes are seldom used.

The most important type of nested class is the inner class. An inner class is a non-static nested class. It has access to all of the variables and methods of its outer class and may refer to them directly in the same way that other non-static members of the outer class do. Thus, an inner class is fully within the scope of its enclosing class.

Types of Nested class ( Detailed )

There are four kinds of nested classes: static member classes, nonstatic member classes, anonymous classes, and local classes.
  1. Static member classes
  2. Member classes
  3. Local classes
  4. Anonymous classes

Sunday, 26 September 2010

Non-static or Member inner class

If a static member class is analogous to a class field or class method, a member class is analogous to an instance field or instance method.

By default, an inner class is non-static:
This fragment defines the class A which contains a non-static inner class B.

A non-static inner class can be instantiated only inside a non-static method of the outer class. This is because every instance of a non-static inner class must be associated with an instance of the outer class. In a sense, every instance of a non-static inner class exists ``inside'' an instance of the outer class. A single instance of the outer class may have associated with it more than one instance of the inner class.
Because an instance of a non-static inner class has an associated instance of the outer class, the methods of the inner class can access directly any of the members (fields or methods) of the outer class instance. For example, the f method defined above can access both x and y directly.
public class A
{
int y;

public class B
{
int x;
void f () {}
}
}
The Java keyword this  can be used in a non-static method to refer to the current object instance. Thus in the method f, this refers to an instance of the inner B class. Every non-static inner class is associated with an instance of A.this.

Use: An Enumeration Implemented as a Member Class
public class LinkedStack {
// Our static member interface; body omitted here...
public static interface Linkable { ... }

// The head of the list
private Linkable head;

// Method bodies omitted here
public void push(Linkable node) { ... }
public Linkable pop() { ... }

// This method returns an Enumeration object for this LinkedStack
public java.util.Enumeration enumerate() { return new Enumerator(); }

// Here is the implementation of the Enumeration interface,
// defined as a member class.

protected class Enumerator implements java.util.Enumeration {
Linkable current
;
// The constructor uses the private head 
    //field of the containing class
public Enumerator() { current = head; }
public boolean hasMoreElements() { return (current != null); }
public Object nextElement() {
if (current == null) throw new java.util.NoSuchElementException();
Object value = current;
current
= current.getNext();
return value;
}
}
}



Restrictions on Member Classes

There are three important restrictions on member classes:
  • A member class cannot have the same name as any containing class or package. This is an important rule, and one not shared by fields and methods.
  • Member classes cannot contain any static fields, methods, or classes (with the exception of constant fields declared both static and final). staticfields, methods, and classes are top-level constructs not associated with any particular object, while every member class is associated with an instance of its enclosing class. Defining a static top-level member within a non-top-level member class simply promotes confusion and bad programming style, so you are required to define all static members within a top-level or static member class or interface.
  • Interfaces cannot be defined as member classes. An interface cannot be instantiated, so there is no object to associate with an instance of the enclosing class. If you declare an interface as a member of a class, the interface is implicitly static, making it a static member class.

New Syntax for Member Classes

The most important feature of a member class is that it can access the instance fields and methods in its containing object. We saw this in theLinkedStack.Enumerator() constructor of above link list example:
public Enumerator() { current = head; }
In this example, head is a field of the LinkedStack class, and we assign it to the current field of the Enumerator class. The current code works, but what if we want to make these references explicit? We could try code like this:
public Enumerator() { this.current = this.head; }
This code does not compile, however. this.current is fine; it is an explicit reference to the current field in the newly created Enumerator object. It is thethis.head expression that causes the problem; it refers to a field named head in the Enumerator object. Since there is no such field, the compiler generates an error. To solve this problem, Java defines a special syntax for explicitly referring to the containing instance of the this object. Thus, if we want to be explicit in our constructor, we can use the following syntax:
public Enumerator() { this.current = LinkedStack.this.head; }
The general syntax is classname.this, where classname is the name of a containing class. Note that member classes can themselves contain member classes, nested to any depth. Since no member class can have the same name as any containing class, however, the use of the enclosing class name prepended to this is a perfectly general way to refer to any containing instance. This syntax is needed only when referring to a member of a containing class that is hidden by a member of the same name in the member class.

Accessing superclass members of the containing class

When a class shadows or overrides a member of its superclass, you can use the keyword super to refer to the hidden member. This super syntax can be extended to work with member classes as well. On the rare occasion when you need to refer to a shadowed field f or an overridden method m of a superclass of a containing class C, use the following expressions:
C.super.f
C.super.m()

This syntax was not implemented by Java 1.1 compilers, but it works correctly as of Java 1.2.

Specifying the containing instance

As we've seen, every instance of a member class is associated with an instance of its containing class. Look again at our definition of the enumerate() method in :
public Enumeration enumerate() { return new Enumerator(); }

When a member class constructor is invoked like this, the new instance of the member class is automatically associated with the this object. This is what you would expect to happen and exactly what you want to occur in most cases. Occasionally, however, you may want to specify the containing instance explicitly when instantiating a member class. You can do this by preceding the new operator with a reference to the containing instance. Thus, the enumerate() method shown above is shorthand for the following:
public Enumeration enumerate() { return this.new Enumerator(); }

Let's pretend we didn't define an enumerate() method for LinkedStack. In this case, the code to obtain an Enumerator object for a given LinkedStackobject might look like this:
LinkedStack stack = new LinkedStack();    // Create an empty stack
Enumeration e = stack.new Enumerator(); // Create an Enumeration for it
The containing instance implicitly specifies the name of the containing class; it is a syntax error to explicitly specify that containing class:
Enumeration e = stack.new LinkedStack.Enumerator();  // Syntax error

There is one other special piece of Java syntax that specifies an enclosing instance for a member class explicitly. Before we consider it, however, let me point out that you should rarely, if ever, need to use this syntax. It is one of the pathological cases that snuck into the language along with all the elegant features of inner classes.
As strange as it may seem, it is possible for a top-level class to extend a member class. This means that the subclass does not have a containing instance, but its superclass does. When the subclass constructor invokes the superclass constructor, it must specify the containing instance. It does this by prepending the containing instance and a period to the super keyword. If we had not declared our Enumerator class to be a protected member of LinkedStack, we could subclass it. Although it is not clear why we would want to do so, we could write code like the following:
// A top-level class that extends a member class
class SpecialEnumerator extends LinkedStack.Enumerator {
// The constructor must explicitly specify a containing instance
// when invoking the superclass constructor.
public SpecialEnumerator(LinkedStack s) { s.super(); }
// Rest of class omitted...
}

Scope Versus Inheritance for Member Classes

We've just noted that a top-level class can extend a member class. With the introduction of member classes, there are two separate hierarchies that must be considered for any class. The first is the classhierarchy, from superclass to subclass, that defines the fields and methods a member class inherits. The second is the containmenthierarchy, from containing class to contained class, that defines a set of fields and methods that are in the scope of (and are therefore accessible to) the member class.
The two hierarchies are entirely distinct from each other; it is important that you do not confuse them. This should not be a problem if you refrain from creating naming conflicts, where a field or method in a superclass has the same name as a field or method in a containing class. If such a naming conflict does arise, however, the inherited field or method takes precedence over the field or method of the same name in the containing class. This behavior is logical: when a class inherits a field or method, that field or method effectively becomes part of that class. Therefore, inherited fields and methods are in the scope of the class that inherits them and take precedence over fields and methods by the same name in enclosing scopes.
Because this can be quite confusing, Java does not leave it to chance that you get it right. Whenever there is a naming conflict between an inherited field or method and a field or method in a containing class, Java requires that you explicitly specify which one you mean. For example, if a member class B inherits a field namedx and is contained within a class A that also defines a field named x, you must use this.x to specify the inherited field and A.this.x to specify the field in the containing class. Any attempt to use the field x without an explicit specification of the desired instance causes a compilation error.
A good way to prevent confusion between the class hierarchy and the containment hierarchy is to avoid deep containment hierarchies. If a class is nested more than two levels deep, it is probably going to cause more confusion than it is worth. Furthermore, if a class has a deep class hierarchy (i.e., it has many superclass ancestors), consider defining it as a top-level class, rather than as a member class.


Tuesday, 15 December 2009

Nesting of classes : Introduction

It is possible to define a class within another class; such classes are known as nested classes.

The scope of a nested class is bounded by the scope of its enclosing class. Also a nested class has access to the members, including private members, of the class in which it is nested. However, the
enclosing class does not have access to the members of the nested class.

Consider the case that class B is defined within class A. So it means:
  • B is known to A, but not outside of A. 
  • B as has access to A's members, including private members.
See types of nested classes .