Thursday, October 3, 2013

Dependency Injection - An Introduction

Dependency

Dependency is when a class needs instances of another class to function correctly.
Following is an example of dependency:
    class X
    {
        ...
        Y obj = new Y("xyz", "abc") ;
        ...
    }

Dependency Problems

  • Dependencies are hardcoded.
  • Unit testing becomes difficult as well, where we need to mock the depencies to perform isolated test cases.
  • With dependencies like above, if different implementation of Y (with same interface) is needed. Actual code needs to be changed.
  • Also the code here is not based on interface so its even further less flexible.
  • If dependency class has further dependencies, those will be needed as well.

Dependency Injection

  • Injecting Dependency from (pushed from) outside into a class at runtime.
  • Dependent object instead of instantiating dependencies using "new" operator from inside of the class should take dependent object via constructor parameters or setters.
  • It decouples class's construction from the construction of its dependencies.
  • Code should depend upon abstractions(interfaces) rathen than implementation(class references).
  • Dependency Injection is for Loose Coupling.
    • An object's dependencies should be on interfaces and not on "concrete" objects.
    • Dependencies should be less.
    • Loose coupling promotes greater reusability, easier maintainability.

    class X
    {
        InterfaceY objY = null;
        ...
        X (InterfaceY dependencyObj)
        {
            objY = dependencyObj ;
         }
        ...
    }

  • Software design pattern that allows the removal of hard-coded dependencies and makes it possible to change them, whether at run-time or compile-time
  • Its a configuration style of prorgamming, object is configured from outside (may be a configuration file) rather than inside.

Primary ways to implement Dependency Injection:

  • Constructor Injection
    • These are considered better than others since at the time of the creation of the class you know what is needed to perform its job.
    • Easier to maintain.
  • Setter Injection
  • Method Injection

How to manage and instantiates dependencies?

  • Each of our classes require dependencies, we need to figure what dependency each class needs and how to instantiate the dependencies.
  • The answer is Dependency Injection container.
  • Dependency Injection container contains map of dedencies needed by a class with the logic to create instances of those dependencies if needed.

Related Topics:
Dependency Inversion Principle
Inversion control Principle
Inversion of Control Container
Dependency Lookup
DI Container Implementations
Butterfly container
factory vs container
factory pattern vs DI Container

Wednesday, October 2, 2013

NESTED CLASSES - Static Nested and Inner Classes

Nested Class:

  • Introduced in version 1.1 of Java.
  • Class within another Class.
  • A nested class is a class whose definition appears inside the definition of another class, as if it were a member of the enclosing class.
  • A nested class can be declared private, public, protected, or package private. 
  • Nested class can be hidden from all other classes using 'private' modifier.
  • Nested Classes are compiled as separate class files with following format:
    • EnclosingClass$InnerClass.class
    • EnclosingClass$StaticNestedClass.class
  • To run main method of nested class, use "java EnclosingClass$StaticNestedClass".
  • Divided into two categories - static and non-static (Inner Classes)
  • Nested class may be nested within another Nested class.
      

      class EnclosingClass {
          ...
          static class StaticNestedClass {
              ...
          }
          class InnerClass {
              ...
          }
      }

Features of Nested Classes:

  • Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private.
  • Static nested classes do not have access to other members of the enclosing class.
  • Inner class is associated with an instance of enclosing instance.
  • A static nested class is associated with enclosing class(not object).
  • The way static methods cannot access non static members, static nested class cannot refer to non-static members without object reference. 
  • Inner Class can access non-static members.
  • Inner class cannot have static members (except constants) because it is linked to an instance of enclosing class.
  • A static nested class is same as any top-level class just that it has been packaged in another top-level class. Only difference is static nested class can access private static members.
  • Inner class instance knows about the enclosing class instance, it can access its members using "<EnclosingClassName>.this".
        this.<member-name> // Inner Class's member
        <EnclosingClassName>.this.<member-name>  // Enclosing Class's member
  • Static nested classes are known as nested top-level classes.
  • An enclosing class can have multiple inner classes extending other classes, thus providing a way to achieve multiple inheritence.
  • Inner class needn't be created at the time of creation of enclosing class, it can be created any time after that.
  • An enclosing class can have multiple instances of same inner class, each with its own state. (Ex. multiple iterators for a rowset).

Typical Usage:

Inner class extends another class or implements an interface (ex. java.util.Iterator). Inner class can access outer class members and closely perform operations on them.
Used for writing test cases, since nested classes have access to private members.
Inner classes are best used in the event handling mechanism and to implement the helper classes.

Why we need Inner Classes:

In the above example, if Iterator would have been a class and not interface, then design couldn't have survived without Inner class, because a class can only extend one class (in that case only Iterator).

Miscellaneous Facts on Nested Classes:

  • Java supports the concept of nested classes in interfaces, though its a teriible programming practice. Following code will compile:
    public interface EnclosingInterface {
        void testMethod();
        class InnerClass {
            int x = 10;
            public void testx() {
                System.out.println(x);
            }
        }
    }
  • Java supports nested interfaces within interfaces but its also a bad programming practice.
  • Java supports nested interfaces within classes, though they are helpful in rare scenarios. These also can be avoided with the use of top-level interfaces.

Local Classes

  • Local classes are classes that are defined in a block, typically inside a method body, though it can be within a loop, if-else blocks etc.
  • Local classes (since its Inner Class) are non-static because they have access to instance members of the enclosing block.
  • A local class (since its Inner Class) has access to the members of its enclosing class.
  • Local classes (since its Inner Class) they cannot define or declare any static members or initializers except constants.
  • Local classes defined in static methods, can only refer to static members of the enclosing class.
  • A local class has access to final local variables as well.
  • local class names are in this format:
    • <EnclosingFormat>$<number><LocalClassName>.class
    • <number> starts with 1, gets incremented by 1 and so on. <number> is coming here because class names can be repeated in different blocks.
    • Ex. EnclosingClass$1LocalA.class, EnclosingClass$1LocalB.class

Anonymous Classes

  • They are like local classes except that they do not have a name.
  • Use them if you need to use a local class only once.
  • They enable you to declare and instantiate a class at the same time. 
  • It is an abbreviated notation for creating a simple local object "in-line" within any expression, simply by wrapping the desired code in a "new" expression.
  • While local classes are class declarations, anonymous classes are like expressions.
  • Anonymous class must be part of a statement since its like an expression.
  • Anonymous classes enable you to make your code more concise.
  • The syntax of an anonymous class expression is like the invocation of a constructor, except that there is a class definition contained in a block of code.
  • Anonymous classes have the same access to local variables of the enclosing scope as local class.
  • Anonymous classes also have the same restrictions as local classes with respect to their members
  • you cannot declare constructors in an anonymous class.
  • Since anonymous classes have no names, the Java compiler uses numbers to provide anonymous class names. Ex. EnclosingClass$1.class.
  • The anonymous class expression consists of the following:
    • The new operator
    • The name of an interface to implement or a class to extend.
    • Parentheses that contain the arguments to a constructor. In case of implementing an interface, there shouldn't be any parameters.
    • Body of class. Method declarations are allowed in body but statements are not. 
  • Syntax:
    new class-name ( [ argument-list ] ) { class-body }
    or:
    new interface-name () { class-body }
    // No argument list with interface.
  • These are mostly used in event handling.
  • They are useful for writing small encapsulated "callbacks," such as enumerations, iterators, visitors, etc.
  • Like local classes, anonymous classes cannot be public, private, protected, or static.  

When to use Member, Local and Anonymous classes?

  • When to use anonymous classes and when to use local classes depends on number of instances needed. If number of instances are more, its local class.
  • When to use local classs and when to use member class depend on the availability of the new type. If wide availability is needed, its member class.

How Inner Classes are Implemented in JVM?

  • Inner classes were introduced in Java 1.1.
  • Introduction of inner classes did not change the Java Virtual Machine or the Java class file format.
  • For Java interpreter and JVM all classes are normal top-level classes.
  • Java compiler inserts hidden fields, methods (getters for instance references), and constructor arguments into the classes it generates. 

Java 8 Enhancements:

  • Local class can access local variables effectively final (whose value is never changed after initialization).
  • Local class can access parameters of the enclosing block, i.e., method parameters in case Local class is defined in a method.