An obsolete reference is one that is kept around but will never be used, preventing the object it refers to from being eligible for garbage collection, thus causing a memory leak.

Manually Setting to NULL
Nulling out a reference to remove obsolete references to an object is good, but one must not overdo it. The best way to eliminate an obsolete reference is to reuse the variable in which it was contained or to let it fall out of scope.

Lets take a Simple Stack implementation as in effective Java

public Object pop() {
    if (size == 0)
        throw new EmptyStackException();
    Object result = elements[--size];
    elements[size] = null; // Eliminate obsolete reference
    return result;
}

In the above code you can see that the stack size is shrinked when ever a pop operation is carried out and is set to null allowing the garbage collector to access the unused space to reclaim

Using WeakHashMap
WeakHashMap is an implementation of the Map interface. WeakHashMap is almost same as HashMap except in case of WeakHashMap, if object is specified as key doesn’t contain any references- it is eligible for garbage collection even though it is associated with WeakHashMap. i.e Garbage Collector dominates over WeakHashMap.

How HashMap Works

// Java program to illustrate 
// Hashmap 
import java.util.*;
class HashMapDemo
{
    public static void main(String args[])throws Exception
    {
        HashMap m = new HashMap();
        Demo d = new Demo();
         
        // puts an entry into HashMap
        m.put(d," Hi "); 
         
        System.out.println(m); 
        d = null;
         
        // garbage collector is called
        System.gc();
         
        //thread sleeps for 4 sec
        Thread.sleep(4000); 
         
        System.out.println(m);
        }
    }
    class Demo
    {
        public String toString()
        {
            return "demo";
        }
         
        // finalize method
        public void finalize()
        {
            System.out.println("Finalize method is called");
        }
}

Output

{demo=Hi}
{demo=Hi}

How WeakHashMap Works

// Java program to illustrate 
// WeakHashmap 
import java.util.*;
class WeakHashMapDemo
{
    public static void main(String args[])throws Exception
    {
        WeakHashMap m = new WeakHashMap();
        Demo d = new Demo();
         
        // puts an entry into WeakHashMap
        m.put(d," Hi "); 
        System.out.println(m);
         
        d = null;
         
        // garbage collector is called
        System.gc(); 
         
        // thread sleeps for 4 sec
        Thread.sleep(4000); .
         
        System.out.println(m);
    }
}
 
class Demo
{
    public String toString()
    {
        return "demo";
    }
     
    // finalize method
    public void finalize()
    {
        System.out.println("finalize method is called");
    }
}

Output

{demo = Hi}
finalize method is called
{ }

There could not be any class which conform to both Same type comparison and Mixed type comparison

Same-Type Comparison
With such an implementation of equals() you can store an Employee(“Hanni Hanuta”) and a Student(“Hanni Hanuta”) into the same HashSet , but retrieval from the collection will not work as expected. You will not find any of these two contained objects when you ask the HashSet whether it contains a Person(“Hanni Hanuta”) , because all three object are unequal to each other.

Mixed-Type Comparison
In a class hierarchy, where Employee and Student are subclasses of a Person , representing roles of a person, it may make sense to compare an Employee to a Student to see whether they are the same Person . With an implementation of equals() that only allows same-type comparison an Employee and a Student would not be comparable.So mixed type comparison allows comparison between parent and child object.With this type of equals() implementation you will have problems storing an Employee(“Hanni Hanuta”) and a Student(“Hanni Hanuta”) in the same HashSet . The HashSet will reject the second add() operation, because the collection already contains an element that compares equal to the new element.

Lets see an example of Mixed-Type comparison

class BaseClass {
    private int field1 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof BaseClass) {
            return field1 == ((BaseClass) obj).field1;
        }
        return false;
    }
}

class BadSubClass extends BaseClass {
    private int field2 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof BadSubClass) {
            return super.equals(obj) 
                    && field2 == ((BadSubClass) obj).field2;
        }
        return false;
    }
}
BaseClass baseClass = new BaseClass();
BadSubClass subClass = new BadSubClass();

System.out.println(baseClass.equals(subClass)); // prints 'true'
System.out.println(subClass.equals(baseClass)); // prints 'false'

Now the above implementation does not comply to symmetric property of equals
x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

The work around for this is

class BaseClass {
    private int field1 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj.getClass() == getClass()) {
            return field1 == ((BaseClass) obj).field1;
        }
        return false;
    }
}

class GoodSubClass extends BaseClass {
    private int field2 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof GoodSubClass) {
            return super.equals(obj) && field2 == ((GoodSubClass) obj).field2;
        }
        return false;
    }
}

Reusing Immutable Object

 
              //Dont Use this
              String strName = new String("Mugil");

              //Use this
              String strName = "Mugil";
         

The Best Example of Immutable Object Reuse is Integer Caching in Java.Lets take the following Example

public class Scratch
{
   public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;  //1
        System.out.println(a == b);

        Integer c = 100, d = 100;  //2
        System.out.println(c == d);
   }
}

Output

false
true

Integer class keeps a cache of Integer instances in the range of -128 to 127, and all autoboxing, literals and uses of Integer.valueOf() will return instances from that cache for the range it covers.

Note that the cache only works if you use auto-boxing or the static method Integer.valueOf(). Calling the constructor will always result in a new instance of integer, even if the value of that instance is in the -128 to 127 range. Integer.valueOf(int). It will return the same Integer object for inputs less than 256.

Reusing Mutable Object

package com.mugil.org.ej;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Item5 
{
	public static void main(String[] args) throws ParseException 
	{
		Person objPerson = new Person();
		objPerson.initializeDates();
		
		
		SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy");
		String endDate = "31-03-2019";
		Date financialYrEndDate = sdf.parse(endDate);
		
		if(financialYrEndDate.after(objPerson.getFinancialYrStartDate()))
		{
			System.out.println("Valid End Date");
		}
	}
}


class Person
{
	private Date financialYrStartDate;	
	
	public void initializeDates() throws ParseException
	{
		SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy");
		String dateInString = "01-04-2018";
		financialYrStartDate = sdf.parse(dateInString);
	}

	public Date getFinancialYrStartDate() {
		return financialYrStartDate;
	}

	public void setFinancialYrStartDate(Date financialYrStartDate) {
		this.financialYrStartDate = financialYrStartDate;
	}	
}

In the above example I know for Sure that the Financial Year End Date should be after Start Date and the Start Date is going to be same for Every Year

package com.mugil.org.ej;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Item5 
{
	public static void main(String[] args) throws ParseException 
	{			
		SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy");
		String endDate = "31-03-2019";
		Date financialYrEndDate = sdf.parse(endDate);
		
		if(financialYrEndDate.after(Person.financialYrStartDate ))
		{
			System.out.println("Valid End Date");
		}
	}
}


class Person
{
	static Date financialYrStartDate;
	
	static
	{	
		SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy");
		String dateInString = "01-04-2018";		
		try {
			financialYrStartDate = sdf.parse(dateInString);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}		
}

Since financialYrStartDate is going to be same it is made as Class Variable which helps to prevent unnecessary Object Creation.

Use Primitives instead of Wrapper Class

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

It takes 43 seconds to run as Long and long primitive brings it down to 6.8 seconds.

Noninstantiable classes are those which can be invoked using object creation.We prefer classes to be Noninstantiable if you want the class to be Utility class with static methods and variables in it.

public final class Useless {
    private Useless() {}
}

A private constructor is the normal object-oriented solution. However, it would still be possible to instantiate such a class using reflection, like this:

Constructor<Useless> con = Useless.class.getDeclaredConstructor();
con.setAccessible(true); // bypass "private"
Useless object = con.newInstance();

To prevent even reflection from working, throw an exception from the constructor:

public final class Useless {
    private Useless() {
        throw new UnsupportedOperationException();
    }
}

Dont Use absract class for NonInstantiable classes

Attempting to enforce noninstantiability by making a class abstract does not work. The class can be subclassed and the subclass instantiated. Furthermore, it misleads the user into thinking the class was designed for inheritance

While Implementing Singleton the following things should be answered

  1. Reflection
  2. Serialization
  3. Cloning

Objects for Singleton Classes implemented using private Constructor can be invoked by Reflection as below

Item3.java

package com.mugil.org.ej;

import java.lang.reflect.Constructor;

public class Item3 {
	public static void main(String[] args) 
	{
		// reflection concept to get constructor of a Singleton class.  
		Constructor<Singleton> constructor;
		
		try {			
			constructor = Singleton.class.getDeclaredConstructor();
			
			// change the accessibility of constructor for outside a class object creation.
			constructor.setAccessible(true);
			
			// creates object of a class as constructor is accessible now.
			Singleton secondOb = constructor.newInstance();
			System.out.println(secondOb.getName());
			
			// close the accessibility of a constructor.
			constructor.setAccessible(false);
		} catch (Exception e){
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
}


class Singleton {

    private static Singleton instance = new Singleton();

    /* private constructor */
    private Singleton() {}

    public static Singleton getDefaultInstance() {
        return instance;
    }
    
    public String getName()
    {
    	return "MyName";
    }
}

Output

MyName

Singleton and Serialization
Without readResolve() Method

// Java code to explain effect of 
// Serilization on singleton classes
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
class Singleton implements Serializable 
{
    // public instance initialized when loading the class
    public static Singleton instance = new Singleton();
     
    private Singleton() 
    {
        // private constructor
    }
}
 
 
public class GFG 
{
 
    public static void main(String[] args) 
    {
        try
        {
            Singleton instance1 = Singleton.instance;
            ObjectOutput out
                = new ObjectOutputStream(new FileOutputStream("file.text"));
            out.writeObject(instance1);
            out.close();
     
            // deserailize from file to object
            ObjectInput in 
                = new ObjectInputStream(new FileInputStream("file.text"));
             
            Singleton instance2 = (Singleton) in.readObject();
            in.close();
     
            System.out.println("instance1 hashCode:- "
                                                 + instance1.hashCode());
            System.out.println("instance2 hashCode:- "
                                                 + instance2.hashCode());
        } 
         
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }
}

Output

instance1 hashCode:- 1550089733
instance2 hashCode:- 785945

With readResolve() Method

// Java code to remove the effect of 
// Serialization on singleton classes
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
class Singleton implements Serializable 
{
    // public instance initialized when loading the class
    public static Singleton instance = new Singleton();
     
    private Singleton() 
    {
        // private constructor
    }
     
    // implement readResolve method
    protected Object readResolve()
    {
        return instance;
    }
}
 
public class GFG 
{
 
    public static void main(String[] args) 
    {
        try
        {
            Singleton instance1 = Singleton.instance;
            ObjectOutput out 
                = new ObjectOutputStream(new FileOutputStream("file.text"));
            out.writeObject(instance1);
            out.close();
         
            // deserailize from file to object
            ObjectInput in 
                = new ObjectInputStream(new FileInputStream("file.text"));
            Singleton instance2 = (Singleton) in.readObject();
            in.close();
         
            System.out.println("instance1 hashCode:- "
                                           + instance1.hashCode());
            System.out.println("instance2 hashCode:- "
                                           + instance2.hashCode());
        } 
         
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

Output

instance1 hashCode:- 1550089733
instance2 hashCode:- 1550089733

Refer http://codethataint.com/blog/singleton-and-serialization/

// JAVA code to explain cloning 
// issue with singleton
class SuperClass implements Cloneable
{
  int i = 10;
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    return super.clone();
  }
}
 
// Singleton class
class Singleton extends SuperClass
{
  // public instance initialized when loading the class
  public static Singleton instance = new Singleton();
 
  private Singleton() 
  {
    // private constructor
  }
}
 
public class GFG
{
  public static void main(String[] args) throws CloneNotSupportedException 
  {
    Singleton instance1 = Singleton.instance;
    Singleton instance2 = (Singleton) instance1.clone();
    System.out.println("instance1 hashCode:- "
                           + instance1.hashCode());
    System.out.println("instance2 hashCode:- "
                           + instance2.hashCode()); 
  }
}

Output

Output :- 
instance1 hashCode:- 366712642
instance2 hashCode:- 1829164700

Two different hashCode means there are 2 different objects of singleton class.

To overcome this issue, override clone() method and throw an exception from clone method that is CloneNotSupportedException. Now whenever user will try to create clone of singleton object, it will throw exception and hence our class remains singleton.

// JAVA code to explain overcome 
// cloning issue with singleton
class SuperClass implements Cloneable
{
  int i = 10;
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    return super.clone();
  }
}
 
// Singleton class
class Singleton extends SuperClass
{
  // public instance initialized when loading the class
  public static Singleton instance = new Singleton();
 
  private Singleton() 
  {
    // private constructor
  }
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    throw new CloneNotSupportedException();
  }
}
 
public class GFG
{
  public static void main(String[] args) throws CloneNotSupportedException 
  {
    Singleton instance1 = Singleton.instance;
    Singleton instance2 = (Singleton) instance1.clone();
    System.out.println("instance1 hashCode:- "
                         + instance1.hashCode());
    System.out.println("instance2 hashCode:- "
                         + instance2.hashCode()); 
  }
}

Output

Output:-
Exception in thread "main" java.lang.CloneNotSupportedException
	at GFG.Singleton.clone(GFG.java:29)
	at GFG.GFG.main(GFG.java:38)

If you don;t want to throw exception you can also return the same instance from clone method.

// JAVA code to explain overcome 
// cloning issue with singleton
class SuperClass implements Cloneable
{
  int i = 10;
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    return super.clone();
  }
}
 
// Singleton class
class Singleton extends SuperClass
{
  // public instance initialized when loading the class
  public static Singleton instance = new Singleton();
 
  private Singleton() 
  {
    // private constructor
  }
 
  @Override
  protected Object clone() throws CloneNotSupportedException 
  {
    return instance;
  }
}
 
public class GFG
{
  public static void main(String[] args) throws CloneNotSupportedException 
  {
    Singleton instance1 = Singleton.instance;
    Singleton instance2 = (Singleton) instance1.clone();
    System.out.println("instance1 hashCode:- "
                           + instance1.hashCode());
    System.out.println("instance2 hashCode:- "
                           + instance2.hashCode()); 
  }
}

Output

Output:-
instance1 hashCode:- 366712642
instance2 hashCode:- 366712642

The Best way to implement Singleton is by using ENUM which takes care of Serialization and Other Issues on its own.

Whenever you submit a form to download a file the response sent back is a file. In this case the setter called after the method which does the download has no effect.

 if(form.getDownloadForm != null && form.getDownloadForm.equals("Y"))
 {
   downloadForm(form, request);

   //The Below Setter has No Effect
   form.setDownloadForm("Y");
 }
 class RegisterForm()
 {
   public String downloadForm;

    public void setDownloadForm(String p_download) 
    {
	  this.downloadForm= p_download;
    }
    
    public String getDownloadForm() 
    {
	  return downloadForm;
    }
 } 

The Setter had no effect since the request sent to the downloadForm(form, request); will end up with response of file download and not response which has new values to form set by setter(in our case downloadForm(form, request)) and Page reload.

There are 2 simple fix for this.

Fix 1
One simple fix is to set form hidden property in java script to N after the form get submitted. Note though the form is submitted it is not reloaded with new response since the response sent back is a file.

The Page will be reloaded only when response is sent back to the same URL of browser. Not to the browser as file.

 function downloadWFSetup(pWaterfallId) 
 {	
    $('#downloadForm').val('Y');
    document.WaterfallTriggerForm.submit();

    //This part of code runs even after the form submission since the 
    //response sent is file which does not require page reload
    $('#downloadForm').val('N');			
 }

In our case the page is not going to get reloaded so the java script continues its execution even after form submission setting property of downloadForm to N.

Fix 2
The Other way is to send request in Link with downloadForm=Y. In this case there is no need to to reset the form values as we get the values by request.getParameter() Method.

The Software development can be grouped in to three phase.
1.Meeting Customer Requirement
2.Applying OOAD Principles
3.Design Patterns

We need to create an app which does search of cars in garage.The search is going to take specification of cars as input and display the matching cars.

Phase 1:

Car.java

 public class Car {

	private String serialNumber;
	private String model;
	private String builder;
	private String price;
	private String type;	

	Car(String pserialNumber, String pmodel, String pbuilder, String pprice, String ptype)
	{
		serialNumber=pserialNumber;
		model=pmodel;
		builder=pbuilder;
		price=pprice;
		type=ptype;
	}

	public String getSerialNumber() {
		return serialNumber;
	}
	public void setSerialNumber(String serialNumber) {
		this.serialNumber = serialNumber;
	}
	public String getModel() {
		return model;
	}
	public void setModel(String model) {
		this.model = model;
	}
	public String getBuilder() {
		return builder;
	}
	public void setBuilder(String builder) {
		this.builder = builder;
	}
	public String getPrice() {
		return price;
	}
	public void setPrice(String price) {
		this.price = price;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}

	public enum Type {
		PETROL, DIESEL;

		public String toString() {

			switch (this) {
			case PETROL:
				return "petrol";

			case DIESEL:
				return "diesel";

			}
			return null;
		}
	}

	public enum Builder {
		FORD, HONDA, TOYOTA;

		public String toString() {
			switch (this) {
			case FORD:
				return "ford";

			case HONDA:
				return "honda";

			case TOYOTA:
				return "toyota";

			}

			return null;
		}

	}
}

Garage.java

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Garage {
	private List<Car> carList = new ArrayList<Car>();

	public void addCar(String pserialNumber, String pmodel, String pbuilder, String pprice, String ptype)
	{
		Car objCar = new Car(pserialNumber, pmodel, pbuilder, pprice, ptype);
		carList.add(objCar);
	}

	//The guitar will be returned only when all Search Criteria Match
	public List<Car> searchCar(Car searchCar)
	{
		List<Car> resultCarList = new ArrayList<Car>(); 

		for (Iterator iterator = carList.iterator(); iterator.hasNext();) {
			Car Car = (Car) iterator.next();

			if(!searchCar.getType().equals(Car.getType()))
				continue;

			if(!searchCar.getBuilder().equals(Car.getBuilder()))
				continue;

			resultCarList.add(Car);
		}

		return resultCarList;
	}

	public Car getCar(String SerialNo)
	{
		return null;
	}
}

SearchCar.java

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

public class SearchCar {
	public static void main(String[] args) throws IOException {
		Garage objGarage = new Garage();
		initializeCar(objGarage);

		Car searchCar = new Car("", "A1", Car.Builder.FORD.toString(), "",
				Car.Type.PETROL.toString());
        List<Car> searchResult  =  objGarage.searchCar(searchCar);

        if(searchResult != null)
        {
        	System.out.println("Search Result");

        	System.out.println("-------------------------------");

			for (Iterator iterator = searchResult.iterator(); iterator.hasNext();) {

				Car Car = (Car) iterator.next();

	        	System.out.println("Model : "+ Car.getModel());
	        	System.out.println("Builder : "+ Car.getBuilder());
	        	System.out.println("Type : "+ Car.getType());
	        	System.out.println("-------------------------------");
			}
        }else
        {
        	System.out.println("Sorry! We are unable to Find Car...");
        }
	}

	public static void initializeCar(Garage pobjGarage) {
		//pserialNumber, pmodel, pbuilder, pprice, ptype
		pobjGarage.addCar("", "Mustang", Car.Builder.FORD.toString(), "", Car.Type.PETROL.toString());
		pobjGarage.addCar("", "Corolla", Car.Builder.TOYOTA.toString(), "", Car.Type.DIESEL.toString());
		pobjGarage.addCar("", "Endevadour", Car.Builder.FORD.toString(), "", Car.Type.PETROL.toString());
		pobjGarage.addCar("", "Civic", Car.Builder.HONDA.toString(), "", Car.Type.PETROL.toString());
	}
}

Points to Note:

  1. When specifications contains less number of search criteria like Fuel Type which can be either petrol or diesel use ENUM.By doing this we are avoiding String comparison and other overheads like converting to lowercase, uppercase before comparison
  2. The searchCar method in Garage will return Cars only when all specs matches the car in the garage.

Phase 2
Object Orientation

  1. Objects should do what their name Indicate
  2. Each Object should represent a Single Concept
  3. Unused properties are dead give away

In the above code the Search criteria used can be split separately.
This includes Type, Model and Builder.
The Price and Serial No are not moved to new class since they are unique.

CarSpec.java

public class CarSpec {

	private String model;
	private String builder;
	private String type;

	public CarSpec(String pbuilder, String pmodel,String ptype){
		model=pmodel;
		builder=pbuilder;
		type=ptype;
	}

	public String getModel() {
		return model;
	}
	public void setModel(String model) {
		this.model = model;
	}
	public String getBuilder() {
		return builder;
	}
	public void setBuilder(String builder) {
		this.builder = builder;
	}

	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
}

Now the car class is going to be replaced with CarSpec variable as property.


public class Car {

	private String serialNumber;
	private String price;
	private CarSpec carSpecification;

	Car(String pserialNumber, String pprice, CarSpec pcarSpec)
	{
		serialNumber=pserialNumber;
		price=pprice;
		carSpecification = pcarSpec;
	}

	public String getSerialNumber() {
		return serialNumber;
	}
	public void setSerialNumber(String serialNumber) {
		this.serialNumber = serialNumber;
	}

	public String getPrice() {
		return price;
	}
	public void setPrice(String price) {
		this.price = price;
	}

	public CarSpec getCarSpecification() {
		return carSpecification;
	}

	public void setCarSpecification(CarSpec carSpecification) {
		this.carSpecification = carSpecification;
	}

	public CarSpec getCarSpec(){
		return carSpecification;
	}
}

Since the Specification of the car are moved separately they can be used for both searching and storing car details.

Now the searchCar() method in Garage.java should be allowed to take car Specification as argument instead of whole car object which contains redundant Price and Serial No which are unique.

Garage.java

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Garage {
	private List<Car> carList = new ArrayList<Car>();

	public void addCar(String pserialNumber, String pprice, CarSpec pcarSpec)
	{
		Car objCar = new Car(pserialNumber, pprice, pcarSpec);
		carList.add(objCar);
	}

	//The guitar will be returned only when all Search Criteria Match
	public List<Car> searchCar(CarSpec searchCarSpec)
	{
		List<Car> resultCarList = new ArrayList<Car>(); 

		for (Iterator iterator = carList.iterator(); iterator.hasNext();) {
			Car objCar = (Car) iterator.next();

			CarSpec objCarSpec = objCar.getCarSpec();

			if(!objCarSpec.getBuilder().equals(searchCarSpec.getBuilder()))
			 continue;

			if(!objCarSpec.getType().equals(searchCarSpec.getType()))
			  continue;

			resultCarList.add(objCar);
		}

		return resultCarList;
	}
}

Searchcar.java

public class SearchCar {
	public static void main(String[] args) throws IOException {
		Garage objGarage = new Garage();
		initializeCar(objGarage);

		CarSpec searchCar = new CarSpec(Builder.FORD.toString(), "", Type.PETROL.toString());
        List<Car> searchResult  =  objGarage.searchCar(searchCar);

        if(searchResult != null)
        {
        	System.out.println("Search Result");

        	System.out.println("-------------------------------");

			for (Iterator iterator = searchResult.iterator(); iterator.hasNext();) {

				Car objCar = (Car) iterator.next();
				CarSpec objSpec = objCar.getCarSpec();

				System.out.println("Car Name : "+ objCar.getSerialNumber());
				System.out.println("Car Name : "+ objCar.getPrice());
	        	System.out.println("Model : "+ objSpec.getModel());
	        	System.out.println("Builder : "+ objSpec.getBuilder());
	        	System.out.println("Type : "+ objSpec.getType());
	        	System.out.println("-------------------------------");
			}
        }else
        {
        	System.out.println("Sorry! We are unable to Find Car...");
        }
	}

	public static void initializeCar(Garage pobjGarage) {
		//pserialNumber, pmodel, pbuilder, pprice, ptype
		pobjGarage.addCar("101", "Mustang", new CarSpec(Builder.FORD.toString(), "3200", Type.PETROL.toString()));
		pobjGarage.addCar("201", "Corolla", new CarSpec(Builder.TOYOTA.toString(), "3500", Type.DIESEL.toString()));
		pobjGarage.addCar("102", "Endevadour", new CarSpec(Builder.FORD.toString(), "5200", Type.PETROL.toString()));
		pobjGarage.addCar("301", "Civic", new CarSpec(Builder.HONDA.toString(), "3000", Type.PETROL.toString()));
	}
}

Now we are going to move the Search Car Code from Garage.java to CarSpec.java.By doing this we are delegating the job to highly coherent class.
In case any code to be added in future the changes to be done are only confined within this class.We are also going to perform object to object comparison.

Garage.java

.
.
.

public List<Car> searchCar(CarSpec searchCarSpec)
	{
		List<Car> resultCarList = new ArrayList<Car>(); 

		for (Iterator iterator = carList.iterator(); iterator.hasNext();) {
			Car objCar = (Car) iterator.next();

			CarSpec objCarSpec = objCar.getCarSpec();

			if(objCarSpec.findMatchingCar(searchCarSpec))
			 resultCarList.add(objCar);
		}

		return resultCarList;
	}

.
.
.

we are calling findMatchingCar method of CarSpec.java instead of doing the comparison in the same class.

CarSpec.java

.
.
.
public boolean findMatchingCar(CarSpec objCarsPEC)
	{
		if(builder !=  objCarsPEC.getBuilder())
		 return false;

		if(type !=  objCarsPEC.getType())
		 return false;

		return true;
	}
.
.
.

————————————————————————————————

Things Learned

  1. Objects should do what their name indicate and should represent a single concept(high cohesion).
    By Moving the specifications on which the search is made into new class CarSpec.java instead of keeping them in Car.java we have achieved high cohesion.
  2. By Delegating the search functionality to class CarSpec.java we have achieved flexibility. In case there
    is new property say four wheel drive or power window added as search criteria the only class file to be changed is CarSpec.java
  3. High cohesion achieved is also evident from the fact that we can do object to object comparing to match the search criteria. findMatchingCar() Method is doing the same.
  4. If object is used with null value or no value you are using object for more than one job.Simple example is doing a null check on a object property which is not a good business code implementation

An aspect is a software entity implementing a specific non-functional part of the application.

Using AOP has 2 Benefits

  1. The logic for each concern is now in one place, as opposed to being scattered all over the code base.
  2. Classes are cleaner since they only contain code for their primary concern (or core functionality) and secondary concerns have been moved to aspects.

OOP and AOP are not mutually exclusive. AOP can be good addition to OOP. AOP is especially handy for adding standard code like logging, performance tracking, etc. to methods without clogging up the method code with this standard code.

Assume you have a graphical class with many “set…()” methods. After each set method, the data of the graphics changed, thus the graphics changed and thus the graphics need to be updated on screen. Assume to repaint the graphics you must call “Display.update()”. The classical approach is to solve this by adding more code. At the end of each set method you write

 void set...(...) {
    :
    :
    Display.update();
}

If you have 3 set-methods, that is not a problem. If you have 200 (hypothetical), it’s getting real painful to add this everywhere. Also whenever you add a new set-method, you must be sure to not forget adding this to the end, otherwise you just created a bug.

AOP solves this without adding tons of code, instead you add an aspect:

after() : set() {
   Display.update();
}

And that’s it! Instead of writing the update code yourself, you just tell the system that after a set() pointcut has been reached, it must run this code and it will run this code. No need to update 200 methods, no need to make sure you don’t forget to add this code on a new set-method. Additionally you just need a pointcut:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

What does that mean? That means if a method is named “set*” (* means any name might follow after set), regardless of what the method returns (first asterisk) or what parameters it takes (third asterisk) and it is a method of MyGraphicsClass and this class is part of the package “com.company.*”, then this is a set() pointcut. And our first code says “after running any method that is a set pointcut, run the following code”.

See how AOP elegantly solves the problem here? Actually everything described here can be done at compile time. A AOP preprocessor can just modify your source (e.g. adding Display.update() to the end of every set-pointcut method) before even compiling the class itself.

However, this example also shows one of the big downsides of AOP. AOP is actually doing something that many programmers consider an “Anti-Pattern”. The exact pattern is called “Action at a distance”.

Action at a distance is an anti-pattern (a recognized common error) in which behavior in one part of a program varies wildly based on difficult or impossible to identify operations in another part of the program.

As a newbie to a project, I might just read the code of any set-method and consider it broken, as it seems to not update the display. I don’t see by just looking at the code of a set-method, that after it is executed, some other code will “magically” be executed to update the display. I consider this a serious downside! By making changes to a method, strange bugs might be introduced. Further understanding the code flow of code where certain things seem to work correctly, but are not obvious (as I said, they just magically work… somehow), is really hard.

OOP and AOP are not mutually exclusive. AOP can be good addition to OOP. AOP is especially handy for adding standard code like logging, performance tracking, etc. to methods without clogging up the method code with this standard code.

AOP addresses the problem of cross-cutting concerns, which would be any kind of code that is repeated in different methods and can’t normally be completely refactored into its own module, like with logging or verification

function mainProgram()
{  
   var x =  foo();
   doSomethingWith(x);
   return x;
 }

 aspect logging
 { 
    before (mainProgram is called):
    { 
       log.Write("entering mainProgram");
    }

     after (mainProgram is called):
    {  
      log.Write(  "exiting mainProgram with return value of "
                + mainProgram.returnValue);
    }
 } 

 aspect verification
 { 
  before (doSomethingWith is called):
  { 
       if (doSomethingWith.arguments[0] == null) 
       { 
         throw NullArgumentException();
       }

      if (!doSomethingWith.caller.isAuthenticated)
      { 
         throw Securityexception();
      }
    }
 }

And then an aspect-weaver is used to compile the code into this:

function mainProgram()
 { 
   log.Write("entering mainProgram");

   var x = foo();   

   if (x == null) throw NullArgumentException();
   if (!mainProgramIsAuthenticated()) throw Securityexception();
   doSomethingWith(x);   

   log.Write("exiting mainProgram with return value of "+ x);
   return x;
 }

Cross Cutting Concerns

  1. Database Access
  2. Data Entities
  3. Email/Notification
  4. Error Handling
  5. Logging

A Wrapper class is any class which “wraps” or “encapsulates” the functionality of another class or component.These are useful by providing a level of abstraction from the implementation of the underlying class or component.

A wrapper class is a class that “wraps” around something else, just like its name.

In general a wrapper is going to expand on what the wrappee does, without being concerned about the implementation of the wrappee, otherwise there’s no point of wrapping versus extending the wrapped class. A typical example is to add timing information or logging functionality around some other service interface, as opposed to adding it to every implementation of that interface.

For example
Wrapper classes provides a way to use the primitive types as objects. For each primitive , we have wrapper class such as for

int Integer
byte Byte 

Integer and Byte are the wrapper classes of primitive int and byte. There are times/restrictions when you need to use the primitives as objects so wrapper classes provide a mechanism called as boxing/unboxing.

Concept can be well understood by the following example as

double d = 135.0 d;

Double doubleWrapper = new Double(d);

int integerValue = doubleWrapper.intValue();
byte byteValue = doubleWrapper.byteValue();
sting stringValue = doubleWrapper.stringValue();

So this is the way , we can use wrapper class type to convert into other primitive types as well. This type of conversion is used when you need to convert a primitive type to object and use them to get other primitives as well.Though for this approach , you need to write a big code . However, the same can be achieved with the simple casting technique as code snippet can be achieved as below

double d = 135.0;
int integerValue = (int) d ;

In general a wrapper is going to expand on what the wrappee does, without being concerned about the implementation of the wrappee, otherwise there’s no point of wrapping versus extending the wrapped class. A typical example is to add timing information or logging functionality around some other service interface, as opposed to adding it to every implementation of that interface.

This then ends up being a typical example for Aspect programming. Rather than going through an interface function by function and adding boilerplate logging, in aspect programming you define a pointcut, which is a kind of regular expression for methods, and then declare methods that you want to have executed before, after or around all methods matching the pointcut. Its probably fair to say that aspect programming is a kind of use of the Decorator pattern, which wrapper classes can also be used for, but that both technologies have other uses.

A boilerplate is a unit of writing that can be reused over and over without change.

A pointcut is a set of join points.

What is Telescoping Constructor Pattern?
In Java, there is no support for default values for constructor parameters. As a workaround, a technique called “Telescoping constructor” is often used. A class has multiple constructors, where each constructor calls a more specific constructor in the hierarchy, which has more parameters than itself, providing default values for the extra parameters.

We’ve all at some point encountered a class with a list of constructors where each addition adds a new option parameter

Pizza(int size) { ... }        
Pizza(int size, boolean cheese) { ... }    
Pizza(int size, boolean cheese, boolean pepperoni) { ... }    
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon) { ... }

Disadvantage
This is called the Telescoping Constructor Pattern. The problem with this pattern is that once constructors are 4 or 5 parameters long it becomes difficult to remember the required order of the parameters as well as what particular constructor you might want in a given situation.

One alternative you have to the Telescoping Constructor Pattern is the JavaBean Pattern where you call a constructor with the mandatory parameters and then call any optional setters after:

Pizza pizza = new Pizza(12);
pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);

The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction. This also requires a lot of extra effort to ensure thread safety.

The better alternative is to use the Builder Pattern.

public class Pizza {
  private int size;
  private boolean cheese;
  private boolean pepperoni;
  private boolean bacon;

  public static class Builder {
    //required
    private final int size;

    //optional
    private boolean cheese = false;
    private boolean pepperoni = false;
    private boolean bacon = false;

    public Builder(int size) {
      this.size = size;
    }

    public Builder cheese(boolean value) {
      cheese = value;
      return this;
    }

    public Builder pepperoni(boolean value) {
      pepperoni = value;
      return this;
    }

    public Builder bacon(boolean value) {
      bacon = value;
      return this;
    }

    public Pizza build() {
      return new Pizza(this);
    }
  }

  private Pizza(Builder builder) {
    size = builder.size;
    cheese = builder.cheese;
    pepperoni = builder.pepperoni;
    bacon = builder.bacon;
  }
}

Note that Pizza is immutable and that parameter values are all in a single location. Because the Builder’s setter methods return the Builder object they are able to be chained.

Pizza pizza = new Pizza.Builder(12)
                       .cheese(true)
                       .pepperoni(true)
                       .bacon(true)
                       .build();

This results in code that is easy to write and very easy to read and understand. In this example, the build method could be modified to check parameters after they have been copied from the builder to the Pizza object and throw an IllegalStateException if an invalid parameter value has been supplied. This pattern is flexible and it is easy to add more parameters to it in the future. It is really only useful if you are going to have more than 4 or 5 parameters for a constructor. That said, it might be worthwhile in the first place if you suspect you may be adding more parameters in the future.

Factory Patterns vs Builder Pattern
Consider a restaurant. The creation of “today’s meal” is a factory pattern, because you tell the kitchen “get me today’s meal” and the kitchen (factory) decides what object to generate, based on hidden criteria.

The builder appears if you order a custom pizza. In this case, the waiter tells the chef (builder) “I need a pizza; add cheese, onions and bacon to it!” Thus, the builder exposes the attributes the generated object should have, but hides how to set them.