Saturday, March 8, 2014

Flavors of Nested Classes in Java 8

Local|non-local|Static|non-static|anonymous class in Java
In this post, we'll explore varieties nested classes such as static nested classes, inner classes, local inner classes and Anonymous inner class with their pros and cons with examples.

Classes defined within the body of another class (or interface) are known as nested classes. Normally you define a class, which is a top-level class directly belonging to a package. In contrast, nested classes are classes contained within another class or interface.


What is the benefit of creating classes inside another class or interface?
  • You can put related classes together as a single logical group.
  • Nested classes can access all class members of the enclosing class, which might be useful in certain cases.
  • Nested classes are sometimes useful for specific purposes. For example, anonymous inner classes are useful for writing simpler event-handling code with AWT/Swing.
So it worth it to learn it!

There are four types or flavors of nested classes in Java

  • Static nested class
  • Inner class
  • Local inner class
  • Anonymous inner class


The distinction among these 4 classes are not clear at first sight. To understand this, see the representation of four flavors of nested classes schematically.


  • A local class is defined within a code block (whether a method, constructor, or initialization block)
  • A non-local class is defined inside a class.
  • A static class is qualified using the static keyword.
  • A non-static class does not use this static keyword with the class definition.
  • In an anonymous class, you don’t provide the name of the class; you just define its body!



From the diagram, it is clear that :

  • Static nested classes are static and non-local, whereas inner classes are non-static and non-local
  • A non-static and local nested class is a local inner class, and a local and anonymous nested class is an anonymous inner class.

Now let's discuss these class in detail.

Static Nested Classes (or Interfaces)
You'll sometimes hear static nested classes referred to as static inner classes, but they really aren't inner classes at all, by the standard definition of an inner class. While an inner class (regardless of the flavor) enjoys that special relationship with the outer class (or rather the instances of the two classes share a relationship), a static nested class does not.

A static nested class is simply a class that's a static member of the enclosing class:

The class itself isn't really "static"; there's no such thing as a static class.
The static modifier in this case says that the nested class is a static member of the outer class. That means it can be accessed, as with other static members, without having an instance of the outer class.

You can define a class (or interface) as a static member inside another class (or interface). Since the outer type can be a class or an interface and the inner ones can also be a class or interface, there are four combinations.
The following are examples of these four types so that you can see their syntax:
You don’t have to explicitly use the static keyword with a nested interface, since it is implicitly static. Check this post for more detail

Instantiating and Using Static Nested Classes
You use standard syntax to access a static nested class from its enclosing class. The syntax for instantiating a static nested class from a non-enclosing class is a little different from a normal inner class.



Points to Remember about static nested classes
  • The accessibility (public, protected, etc.) of the static nested class is defined by the outer class.
  • A static nested class is not an inner class, it's a top-level nested class.
  • The name of the static nested class is expressed with OuterClassName.NestedClassName syntax.
  • When you define an inner nested class (or interface) inside an interface, the nested class is declared implicitly public and static. This point is easy to remember: any field in an interface is implicitly declared public and static, and static nested classes have this same behavior.Static nested classes can be declared abstract or final.
  • Static nested classes can extend another class or it can be used as a base class.
  • Static nested classes can have static members. 
  • Static nested classes can access the members of the outer class (only static members, obviously).
  • The outer class can also access the members (even private members) of the nested class through an object of nested class. If you don’t declare an instance of the nested class, the outer class cannot access nested class elements directly.



Inner Classes
You can define a class (or an interface) as a non-static member inside another class. How about declaring a class or an interface inside an interface?
As you just saw in the above about static inner classes, when you define a class or an interface inside an interface, it is implicitly static. So, it is not possible to declare a non-static inner interface! That leaves two possibilities:

The outer and inner classes share a special relationship, like friends or members of same family. Member accesses are valid irrespective of the access specifiers such as private. However, there is subtle difference. 
You can access members of an outer class within an inner class without creating an instance; but this is not the case with an outer class. You need to create an instance of inner class in order to access the members (any members, including private members) of the inner class.

One limitation of inner classes is that you cannot declare static members in an inner class, like this


Instantiating an Inner Class
To create an instance of an inner class, you must have an instance of the outer class to tie to the inner class. There are no exceptions to this rule: an inner class instance can never stand alone without a direct relationship to an instance of the outer class

Instantiating an Inner Class from Within the Outer Class

You can see in the preceding code that the Outer code treats Inner just as though Inner were any other accessible class—it instantiates it using the class name (new Inner()), and then invokes a method on the reference variable (inner.go()). But the only reason this syntax works is because the outer class instance method code is doing the instantiating.

Creating an Inner Class Object from Outside the Outer Class Instance Code
If we want to create an instance of the inner class, we must have an instance of the outer class. You already know that, but think about the implications it means that, without a reference to an instance of the outer class, you can't instantiate the inner class from a static method of the outer class because, don't forget, in static code there is no this reference.
Inner class instances are always handed an implicit reference to the outer class. The compiler takes care of it, so you'll never see anything but the end result—the ability of the inner class to access members of the outer class.

Referencing the Inner or Outer Instance from Within the Inner Class
How does an object refer to itself normally? By using the this reference
Quick review of this

  • The keyword this can be used only from within instance code. In other words, not within static code.
  • The this reference is a reference to the currently executing object.
  • The this reference is the way an object can pass a reference to itself to some other code, as a method argument
Within an inner class code, the this reference refers to the instance of the inner class, as you'd probably expect, since this always refers to the currently executing object.
But what if the inner class code wants an explicit reference to the outer class instance that the inner instance is tied to? In other words, how do you reference the "outer this"?
Using reference the "outer this" (the outer class instance) from within the inner class code, use NameOfOuterClass.this 


Points to Remember about Inner class
  • The accessibility (public, protected, etc.) of the inner class is defined by the outer class.
  • Just like top-level classes, an inner class can extend a class or can implement interfaces. Similarly, an inner class can be extended by other classes, and an inner interface can be implemented or extended by other classes or interfaces.
  • An inner class can be declared final or abstract.
  • Inner classes can have inner classes, but you’ll have a hard time reading or understanding such complex nesting of classes.

Member Modifiers Applied to Inner Classes 
A regular inner class is a member of the outer class just as instance variables and methods are, so the following modifiers can be applied to an inner class:

  • final
  • abstract
  • public
  • private
  • private
  • static—but static turns it into a static nested class not an inner class
  • strictfp


Local Inner Classes
A local inner class is defined in a code block (say, in a method, constructor, or initialization block). Unlike static nested classes and inner classes, local inner classes are not members of an outer class; they are just local to the method or code in which they are defined.

As you can see in this code, Local is a class defined within someFunction. It is not available outside of someFunction, not even to the members of the SomeClass. Since you cannot declare a local variable static, you also cannot declare a local class static.

Since you cannot define methods in interfaces, you cannot have local classes or interfaces inside an interface. Nor can you create local interfaces. In other words, you cannot define interfaces inside methods, constructors, and initialization blocks.


This code declare a class Outer with one method go().  But inside go(), another class MethodLocalInner is declared and it has a method of its own. This code is useless ,however, because it never instantiate the inner class! Just because you declared the class doesn't mean you created an instance of it.
So to use the inner class you must make an instance of it somewhere within the method but below the inner class definition. See the next example.


Instantiating method-local inner class
A method-local inner class can be instantiated only within the method where the inner class is defined.
Like regular inner class objects, the method-local inner class object shares a special relationship with the enclosing (outer) class object, and can access its private (or any other) members. However, the inner class object cannot use the local variables of the method the inner class is in. Why not?
The local variables of the method live on the stack, and exist only for the lifetime of the method.
When the method ends, the stack  frame is blown away and the variable is history. But even after the method completes, the inner class object created within it might still be alive on the heap if, for example, a reference to it was passed into some other code and then stored in an instance variable.
Because the local variables aren't guaranteed to be alive as long as the method-local inner class object, the inner class object can't use them. Unless the local variables are marked final !
A local class can have static members provided that they are constant variables


eclipse ex 



However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.
For example, suppose that the variable local_method_variable is not declared final, and you are changing it value then it is effectively final so you can use it in method local inner classes.
But if try to change the value of local_method_variable, then it is no longer effectively final, you get compiler error. Let's see two example:



Points to Remember about method-local inner classes
  • You can create a non-static local class inside a body of code. Interfaces cannot have local  classes, and you cannot create local interfaces.
  • Local classes are accessible only from the body of the code in which the class is defined. The local classes are completely inaccessible outside the body of the code in which the class is defined.
  • You can extend a class or implement interfaces while defining a local class.
  • A local class can access all the variables available in the body of the code in which it is defined. You can pass only final variables to a local inner class.

Shadowing in inner class and method-local inner class
If a declaration of a type (such as a member variable or a parameter name) in a particular scope (such as an inner class or a method definition) has the same name as another declaration in the enclosing scope, then the declaration shadows the declaration of the enclosing scope. You cannot refer to a shadowed declaration by its name alone.

x=10
this.x=10
MyOuter.this.x=0


method variable javalatte
class variable javalatte
Enclosing class var java


Anonymous Inner Classes
As the name implies, an anonymous inner class does not have a name. The declaration of the class automatically derives from the instance-creation expression. They are also referred to simply as anonymous classes.


An anonymous class is useful in almost all situations where you can use local inner classes. A local inner class has a name, whereas an anonymous inner class does not—and that’s the main difference! An additional difference is that an anonymous inner class cannot have any explicit constructors.  A constructor is named after the name of the class, and since an anonymous class has no name, it follows that you cannot define a constructor!
While local classes are class declarations, anonymous classes are expressions, which means that you define the class in another expression

Flavor One creates an anonymous subclass of the specified class type

Flavor two creates an anonymous implementer of the specified interface type


Points to Remember about anonymous classes
  • Anonymous classes are defined in the new expression itself, so you cannot create multiple objects of an anonymous class.
  • You cannot explicitly extend a class or explicitly implement interfaces when defining an anonymous class.
  • An anonymous inner class is always created as part of a statement; don't forget to close the statement after the class definition with a curly brace. This is a rare case in Java, a curly brace followed by a semicolon.
  • Anonymous inner classes have no name, and their type must be either a subclass of the named type or an implementer of the named interface
However, starting in Java SE 8Anonymous classes are used in Lambda expression.


When to Use Nested Classes, Local Classes, Anonymous Classes, and Lambda Expressions

Local class : Use it if you need to create more than one instance of a class, access its constructor, or introduce a new, named type (because, for example, you need to invoke additional methods later).

Anonymous class: Use it if you need to declare fields or additional methods.

Lambda expression:

  • Use it if you are encapsulating a single unit of behavior that you want to pass to other code. For example, you would use a lambda expression if you want a certain action performed on each element of a collection, when a process is completed, or when a process encounters an error.
  • Use it if you need a simple instance of a functional interface and none of the preceding criteria apply (for example, you do not need a constructor, a named type, fields, or additional methods).

Nested class
  • Use it if your requirements are similar to those of a local class, you want to make the type more widely available, and you don't require access to local variables or method parameters.
  • Use a non-static nested class (or inner class) if you require access to an enclosing instance's non-public fields and methods. Use a static nested class if you don't require this access.


If you know anyone who has started learning java, why not help them out! Just share this post with them. 
Thanks for studying today!...

3 comments:

  1. how the fuck did u do this man ...? I've just read it till the Static Nested Classes and enjoying this stuff. Cool... !! Am going to explore ur blog for more.

    ReplyDelete