Solved

Nested Interfaces and Classes

Posted on 2004-09-23
12
439 Views
Last Modified: 2012-08-13
Please let me know the functionalities and usage of "Nested Interfaces" and "Classes" in JAVA. It's crucial to support the statements with small code snippets so that it goes into my brain. :-)

Regards,
perfect_tranquility
0
Comment
Question by:perfect_tranquility
12 Comments
 
LVL 92

Accepted Solution

by:
objects earned 100 total points
ID: 12139560
0
 
LVL 21

Assisted Solution

by:MogalManic
MogalManic earned 100 total points
ID: 12139791
A nested class/interface, also known as inner classes, are meant for classes that depend on the functionality defined by the outer class.  For example the java.util.Map interface contains an inner interface called Map.Entry.  The Map.Entry interface contains the Key and Value one entry in a Map.  You cannot create a Map.Entry without first creating a Map.

An inner (non-static) class has access to its class members as well as its parent classes members.  Consider this example:

class foo
{
   int x=5;
   bar barRef=new bar();

   class bar
   {
       int x=5;
       public void method()
       {
           this.x=this.foo.x*this.x;
           this.foo.method();
       }
   }


   public void method()
   {
       this.x=this.x+1;
   }

   public static int main(String[] args)
   {
        foo y=new foo();
        y.method();
        y.barRef.method();
        System.out.println("y.x="+y.x);
        System.out.println("y.barRef.x="+y.barRef.x);
}

This example will output:
    y.x=7
    y.barRef.x=30
0
 
LVL 14

Assisted Solution

by:sudhakar_koundinya
sudhakar_koundinya earned 100 total points
ID: 12140373
Java lets you define a class as a member of another class. Such a class is called a nested class and is illustrated here:

class EnclosingClass{
    . . .
    class ANestedClass {
        . . .
    }
}

    Definition:  A nested class is a class that is a member of another class.

You use nested classes to reflect and enforce the relationship between two classes. You should define a class within another class when the nested class makes sense only in the context of its enclosing class or when it relies on the enclosing class for its function. For example, a text cursor makes sense only in the context of a particular text component.

As a member of its enclosing class, a nested class has a special privilege: It has unlimited access to its enclosing class's members, even if they are declared private. However, this special privilege isn't really special at all. It is fully consistent with the meaning of private and the other access specifiers. The access specifiers restrict access to members for classes outside of the enclosing class. The nested class is inside of its enclosing class so that it has access to its enclosing class's members.

Like other members, a nested class can be declared static (or not). A static nested class is called just that: a static nested class. A nonstatic nested class is called an inner class. These are illustrated in the following code:

class EnclosingClass{
    . . .
    static class AStaticNestedClass {
        . . .
    }
    class InnerClass {
        . . .
    }
}

As with static methods and variables (normally called class methods and variables), a static nested class is associated with its enclosing class. And like class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class-it can use them only through an object reference.

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's instance variables and methods. Also, because an inner class is associated with an instance, it cannot define any static members itself.

To help differentiate the terms nested class and inner class further, we suggest you think about them in the following way. The term "nested class" reflects the syntactic relationship between two classes; that is, syntactically, the code for one class appears within the code of another. In contrast, the term "inner class" reflects the relationship between instances of the two classes. Consider the following classes:

class EnclosingClass {
    . . .
    class InnerClass {
        . . .
    }
}

The interesting feature about the relationship between these two classes is not that InnerClass is syntactically defined within EnclosingClass. Rather, it's that an instance of InnerClass can exist only within an instance of EnclosingClass and that it has direct access to instance variables and methods of its enclosing instance



    You may encounter nested classes of both kinds in the Java API and be required to use them. However, most nested classes that you write will be inner classes.

        Definition:  An inner class is a nested class whose instance exists within an instance of its enclosing class and has direct access to the instance members of its enclosing instance.

Other Facts about Nested Classes

    Like other classes, nested classes can be declared abstract or final. The meaning of these two modifiers for nested classes is the same as for other classes. Also, the access specifiers--private, public, protected, and package--- may be used to restrict access to nested classes just as they do to other class members.

    Any nested class, not just anonymous ones, can be declared in any block of code. A nested class declared within a method or other smaller block of code has access to any final, local variables in scope.
0
 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 12140382
Nested classes are simply static inner classes. The difference between nested classes and inner classes is the same as the difference between static and nonstatic members of a class: nested classes are associated with the enclosing class itself, whereas inner classes are associated with an object of the enclosing class.

Because of this, inner class objects require an object of the enclosing class, while nested class objects do not. Nested classes, therefore, behave just like top-level classes, using the enclosing class to provide a package-like organization. In addition, nested classes have access to all members of the enclosing class.
0
 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 12140392
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 12140417
0
 
LVL 4

Assisted Solution

by:JK2429
JK2429 earned 100 total points
ID: 12142223
0
 
LVL 9

Assisted Solution

by:doronb
doronb earned 100 total points
ID: 12194541
First compile this class:

import java.util.*;
import java.lang.reflect.*;

public class IteratorVisitor {
      private final static Hashtable visitors = new Hashtable();
      private ItemVisitor itemVisitor;
      private Class[] visitorParamTypes;
      private Object[] visitorParams;
      private Method visitorMethd;

      public interface ItemVisitor {}

      public static Object visitIterator(Iterator iter, ItemVisitor visitor) {
            return visitIterator(false, iter, visitor);
      }

      public static Object visitIterator(boolean allMatches, Iterator iter, ItemVisitor visitor) {
            Class visitorClass = visitor.getClass();
            IteratorVisitor iv = (IteratorVisitor)visitors.get(visitorClass);
            if (iv == null) {
                  iv = new IteratorVisitor(visitor);
                  visitors.put(visitorClass, iv);
            } else {
                  iv.itemVisitor = visitor;
            }
            iv.visitIterator(allMatches, iter);
            return iv.visitorParams[1];
      }

      private IteratorVisitor(ItemVisitor itemVisitor) {
            this.itemVisitor = itemVisitor;
            Class[] classTypes = null;
            Method[] methods = itemVisitor.getClass().getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                  visitorMethd = methods[i];
                  if (visitorMethd.getName().equals("visitNextItem")) {
                        classTypes = visitorMethd.getParameterTypes();
                        if (classTypes != null && classTypes.length == 2 && classTypes[0] == Iterator.class) {
                              visitorParamTypes = new Class[] {Iterator.class, classTypes[1]};
                              visitorParams = new Object[2];
                              return;
                        }
                  }
            }
            itemVisitor = null;
            visitorParamTypes = null;
            visitorParams = null;
            visitorMethd = null;
      }

      private void visitIterator(boolean allMatches, Iterator iter) {
            Vector items = null;
            Boolean quitFlag = null;
            boolean done = false;
            if (visitorMethd != null && iter != null) {
                  visitorParams[0] = iter;
                  while (!done && iter.hasNext()) {
                        visitorParams[1] = iter.next();
                        try {
                              quitFlag = ((Boolean)visitorMethd.invoke(itemVisitor, visitorParams));
                              if (quitFlag != null) {
                                    done = quitFlag.booleanValue();
                                    if (done && allMatches) {
                                          done = false;
                                          if (items == null) {
                                                items = new Vector();
                                          }
                                          items.addElement(visitorParams[1]);
                                    }
                              }
                        } catch (InvocationTargetException ex) {
                        } catch (IllegalArgumentException ex) {
                        } catch (IllegalAccessException ex) {
                        }
                  }
                  if (!done) {
                        visitorParams[1] = (items == null) ? null : items.toArray();
                  }
            }
      }
}

Now, every time you need to go through an Iterator to perform some boring task, you can do something like this:

      public static void displayAllMatches(final String name, Iterator iter) {
            IteratorVisitor.visitIterator(iter, new IteratorVisitor.ItemVisitor() {
                  public void visitNextItem(Iterator iter, Person person) {
                        if (person.getLastName().equals(name)) {
                              System.out.println(person);
                        }
                  }
            });
      }

      public static Object returnFirstMatch(final String name, Iterator iter) {
            return IteratorVisitor.visitIterator(iter, new IteratorVisitor.ItemVisitor() {
                  public boolean visitNextItem(Iterator iter, Person person) {
                        return (person.getLastName().equals(name));
                  }
            });
      }

      public static Object[] returnAllMatches(final String name, Iterator iter) {
            return (Object[])IteratorVisitor.visitIterator(true, iter, new IteratorVisitor.ItemVisitor() {
                  public boolean visitNextItem(Iterator iter, Person person) {
                        return (person.getLastName().equals(name));
                  }
            });
      }

As you can see, each of the visitNextItem(Iterator, <Object>) already accepts the proper instance already casted to whatever you need. :)
0
 
LVL 9

Expert Comment

by:doronb
ID: 12194623
Another example I have has to do with Delegates :)

I start off with this:

public interface Delegate {
      public void register(Object instance, String methodName) throws IllegalArgumentException;
      public void unRegister(Object instance, String methodName) throws IllegalArgumentException;
      public void unRegister(Object instance) throws IllegalArgumentException;
      public void register(Class instanceClass, String methodName) throws IllegalArgumentException;
      public void unRegister(Class instanceClass, String methodName) throws IllegalArgumentException;
      public void unRegister(Class instanceClass) throws IllegalArgumentException;
      public boolean hasExceptions();
      public Throwable[] getExceptions();
}

Then, I can build on the Delegate interface and do this:

public interface IntTestInterface extends Delegate {
      public int operateOnTwoNumbers(int a, int b);
      public IntTestInterface Delegate = (IntTestInterface)DelegateManager.CreateDelegate(IntTestInterface.class);
}

public interface VoidTestInterface extends Delegate {
      public void operateOnTwoNumbers(int a, int b);
      public VoidTestInterface Delegate = (VoidTestInterface)DelegateManager.CreateDelegate(VoidTestInterface.class);
}

After defining the test interfaces, my test program looks like this:

public class TestApp {
      private interface MaxOperation extends Delegate {
            public int max(int val0, int val1);
      }

      private MaxOperation maxDelegate = (MaxOperation)DelegateManager.CreateDelegate(MaxOperation.class);

      private static final IntTestInterface intTester = IntTestInterface.Delegate;
      private static final VoidTestInterface voidTester = VoidTestInterface.Delegate;

      public TestApp() {
            maxDelegate.register(this, "findMaxValue");
      }

      public static void main(String[] args) {
            TestApp ta = new TestApp();
            try {
                  voidTester.register(ta, "vAddTwoNumbers");
                  voidTester.register(TestApp.class, "vSubTwoNumbers");
                  intTester.register(ta, "addTwoNumbers");
                  intTester.register(TestApp.class, "subTwoNumbers");
            } catch (IllegalArgumentException ex) {
                  ex.printStackTrace();
            }
            System.out.println(intTester.operateOnTwoNumbers(2, 3));
            showExceptions(intTester);
            voidTester.operateOnTwoNumbers(7, 9);
            showExceptions(voidTester);
            System.out.println(ta.maxDelegate.max(1000, 999));
            System.out.println("Test Complete.");
      }

      private static void showExceptions(Delegate delegate) {
            if (delegate.hasExceptions()) {
                  Throwable[] exceptionList = delegate.getExceptions();
                  for (int i = 0; i < exceptionList.length; i++) {
                        exceptionList[i].printStackTrace();
                  }
            }
      }

      private int findMaxValue(int value0, int value1) {
            return Math.max(value0, value1);
      }

      private int addTwoNumbers(int numberOne, int numberTwo) {
            return (numberOne + numberTwo);
      }

      private void vAddTwoNumbers(int numberOne, int numberTwo) {
            System.out.println((numberOne + numberTwo));
      }

      private static int subTwoNumbers(int numberOne, int numberTwo) {
            return (numberOne - numberTwo);
      }

      private static void vSubTwoNumbers(int numberOne, int numberTwo) {
            if (numberOne == 7) {
                  throw new NullPointerException("OOPS!");
            }
            System.out.println(numberOne - numberTwo);
      }
}

The output follows:

java.lang.IllegalArgumentException: Only one Non-Void Method is allowed to register.
      at com.pss.util.delegates.TestApp.main(TestApp.java:23)
java.lang.NullPointerException: OOPS!
      at com.pss.util.delegates.TestApp.vSubTwoNumbers(TestApp.java:62)
      at com.pss.util.delegates.TestApp.main(TestApp.java:29)
5
16
1000
Test Complete.

Of course none of this would work for you right now since DelegateManager is missing, but I the point is, inner interfaces and classes are quite useful.
0
 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 12450555
:)
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
This video teaches viewers about errors in exception handling.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now