Top Banner
Encapsulation Encapsulation is one of the four fundamental OOP concepts. The other three are inheritance, polymorphism, and abstraction. Encapsulation is the technique of making the fields in a class private and providing access to the fields via public methods. If a field is declared private, it cannot be accessed by anyone outside the class, thereby hiding the fields within the class. For this reason, encapsulation is also referred to as data hiding. Encapsulation can be described as a protective barrier that prevents the code and data being randomly accessed by other code defined outside the class. Access to the data and code is tightly controlled by an interface. The main benefit of encapsulation is the ability to modify our implemented code without breaking the code of others who use our code. With this feature Encapsulation gives maintainability, flexibility and extensibility to our code. Example: Let us look at an example that depicts encapsulation: /* File name : EncapTest.java */ public class EncapTest{ private String name; private String idNum; private int age; public int getAge(){ return age; } public String getName(){ return name; } public String getIdNum(){ return idNum; } public void setAge( int newAge){ age = newAge; } public void setName(String newName){ name = newName; } public void setIdNum( String newId){ idNum = newId; } } The public methods are the access points to this class’s fields from the outside java world. Normally these methods are referred as getters and setters. Therefore any class that wants to access the variables should access them through these getters and setters. The variables of the EncapTest class can be access as below::
31
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java

EncapsulationEncapsulation is one of the four fundamental OOP concepts. The other three are inheritance, polymorphism, and abstraction.Encapsulation is the technique of making the fields in a class private and providing access to the fields via public methods. If a field is declared private, it cannot be accessed by anyone outside the class, thereby hiding the fields within the class. For this reason, encapsulation is also referred to as data hiding.Encapsulation can be described as a protective barrier that prevents the code and data being randomly accessed by other code defined outside the class. Access to the data and code is tightly controlled by an interface.The main benefit of encapsulation is the ability to modify our implemented code without breaking the code of others who use our code. With this feature Encapsulation gives maintainability, flexibility and extensibility to our code.Example:Let us look at an example that depicts encapsulation:

/* File name : EncapTest.java */public class EncapTest{

private String name; private String idNum; private int age;

public int getAge(){ return age; }

public String getName(){ return name; }

public String getIdNum(){ return idNum; }

public void setAge( int newAge){ age = newAge; }

public void setName(String newName){ name = newName; }

public void setIdNum( String newId){ idNum = newId; }}

The public methods are the access points to this class’s fields from the outside java world. Normally these methods are referred as getters and setters. Therefore any class that wants to access the variables should access them through these getters and setters.The variables of the EncapTest class can be access as below::

/* File name : RunEncap.java */public class RunEncap{ public static void main(String args[]){ EncapTest encap = new EncapTest(); encap.setName("James"); encap.setAge(20); encap.setIdNum("12343ms"); System.out.print("Name : " + encap.getName()+ " Age : "+ encap.getAge()); }

Page 2: Java

}

This would produce following result:

Name : James Age : 20

Benefits of Encapsulation:The fields of a class can be made read-only or write-only.A class can have total control over what is stored in its fields.The users of a class do not know how the class stores its data. A class can change the data type of a field, and users of the class do not need to change any of their code.

InheritanceInheritance can be defined as the process where one object acquires the properties of another. With the use of inheritance the information is made manageable in a hierarchical order. When we talk about inheritance the most commonly used keyword would be extends and implements. These words would determine whether one object IS-A type of another. By using these keywords we can make one object acquire the properties of another object.IS-A Relationship:IS-A is a way of saying: This object is a type of that object. Let us see how the extends keyword is used to achieve inheritance.

public class Animal{}

public class Mammal extends Animal{}

public class Reptile extends Animal{}

public class Dog extends Mammal{}

Now based on the above example, In Object Oriented terms following are true:Animal is the superclass of Mammal class.Animal is the superclass of Reptile class.Mammal and Reptile are sub classes of Animal class.Dog is the subclass of both Mammal and Animal classes.Now if we consider the IS-A relationship we can say:Mammal IS-A AnimalReptile IS-A AnimalDog IS-A MammalHence : Dog IS-A Animal as wellWith use of the extends keyword the subclasses will be able to inherit all the properties of the superclass except for the private properties of the superclass.We can assure that Mammal is actually an Animal with the use of the instance operator.Example:

public class Dog extends Mammal{ public static void main(String args[]){ Animal a = new Animal(); Mammal m = new Mammal(); Dog d = new Dog();

System.out.println(m instanceof Animal); System.out.println(d instanceof Mammal); System.out.println(d instanceof Animal); }}

This would produce following result:

true

Page 3: Java

truetrue

Since we have a good understanding of the extends keyword let us look into how the implements keyword is used to get the IS-A relationship.The implements keyword is used by classes by inherit from interfaces. Interfaces can never be extended.Example:

public interface Animal {}

public class Mammal implements Animal{}

public class Dog extends Mammal{}

The instanceof Keyword:Let us use the instanceof operator to check determine whether Mammal is actually an Animal, and dog is actually an Animal

interface Animal{}

class Mammal implements Animal{}

class Dog extends Mammal{ public static void main(String args[]){

Mammal m = new Mammal(); Dog d = new Dog();

System.out.println(m instanceof Animal); System.out.println(d instanceof Mammal); System.out.println(d instanceof Animal); }}

This would produce following result:

truetruetrue

HAS-A relationship:These relationships are mainly based on the usage. This determines whether a certain class HAS-A certain thing. This relationship helps to reduce duplication of code as well as bugs.Lets us look into an example:

public class Vehicle{}public class Speed{}public class Van extends Vehicle{

private Speed sp;}

This shows that class Van HAS-A Speed. By having a separate class for Speed we do not have to put the entire code that belongs to speed inside the Van class., which makes it possible to reuse the Speed class in multiple applications.In Object Oriented feature the users do not need to bother about which object is doing the real work. To achieve this, the Van class hides the implementation details from the users of the Van class. SO basically what happens is the users would ask the Van class to do a certain action and the Vann class will either do the work by itself or ask another class to perform the action.A very important fact to remember is that Java only supports only single inheritance. This means that a class cannot extend more than one class. Therefore following is illegal:

public class extends Animal, Mammal{}

Page 4: Java

However a class can implement one or more interfaces. This has made Java get rid of the impossibility of multiple inheritance.

PolymorphismPolymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object.Any java object that can pass more than on IS-A test is considered to be polymorphic. In Java, all java objects are polymorphic since any object will pass the IS-A test for their own type and for the class Object.It is important to know that the only possible way to access an object is through a reference variable. A reference variable can be of only one type. Once declared the type of a reference variable cannot be changed.The reference variable can be reassigned to other objects provided that it is not declared final. The type of the reference variable would determine the methods that it can invoke on the object.A reference variable can refer to any object of its declared type or any subtype of its declared type. A reference variable can be declared as a class or interface type.Example:Let us look at an example.

public interface Vegetarian{}public class Animal{}public class Deer extends Animal implements Vegetarian{}

Now the Deer class is considered to be polymorphic since this has multiple inheritance. Following are true for the above example:A Deer IS-A AnimalA Deer IS-A VegetarianA Deer IS-A DeerA Deer IS-A ObjectWhen we apply the reference variable facts to a Deer object reference, the following declarations are legal:

Deer d = new Deer();Animal a = d;Vegetarian v = d;Object o = d;

All the reference variables d,a,v,o refer to the same Deer object in the heap.Virtual Methods:In this section, I will show you how the behavior of overridden methods in Java allows you to take advantage of polymorphism when designing your classes.We already have discussed method overriding, where a child class can override a method in its parent. An overridden method is essentially hidden in the parent class, and is not invoked unless the child class uses the super keyword within the overriding method.

/* File name : Employee.java */public class Employee{ private String name; private String address; private int number; public Employee(String name, String address, int number) { System.out.println("Constructing an Employee"); this.name = name; this.address = address; this.number = number; } public void mailCheck() { System.out.println("Mailing a check to " + this.name + " " + this.address);

Page 5: Java

} public String toString() { return name + " " + address + " " + number; } public String getName() { return name; } public String getAddress() { return address; } public void setAddress(String newAddress) { address = newAddress; } public int getNumber() { return number; }}

Now suppose we extend Employee class as follows:

/* File name : Salary.java */public class Salary extends Employee{ private double salary; //Annual salary

public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("Within mailCheck of Salary class "); System.out.println("Mailing check to " + getName() + " with salary " + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; }}

Now you study the following program carefully and try to determine its output:

/* File name : VirtualDemo.java */public class VirtualDemo{ public static void main(String [] args) {

Page 6: Java

Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00); Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00); System.out.println("Call mailCheck using Salary reference --"); s.mailCheck(); System.out.println("\n Call mailCheck using Employee reference--"); e.mailCheck(); }}

This would produce following result:

Constructing an EmployeeConstructing an EmployeeCall mailCheck using Salary reference --Within mailCheck of Salary classMailing check to Mohd Mohtashim with salary 3600.0

Call mailCheck using Employee reference--Within mailCheck of Salary classMailing check to John Adams with salary 2400.0

Here we instantiate two Salary objects . one using a Salary reference s, and the other using an Employee reference e.While invoking s.mailCheck() the compiler sees mailCheck() in the Salary class at compile time, and the JVM invokes mailCheck() in the Salary class at run time.Invoking mailCheck() on e is quite different because e is an Employee reference. When the compiler sees e.mailCheck(), the compiler sees the mailCheck() method in the Employee class.Here, at compile time, the compiler used mailCheck() in Employee to validate this statement. At run time, however, the JVM invokes mailCheck() in the Salary class.This behavior is referred to as virtual method invocation, and the methods are referred to as virtual methods. All methods in Java behave in this manner, whereby an overridden method is invoked at run time, no matter what data type the reference is that was used in the source code at compile time.

COMPOSITION – ASSOCIATION – AGGREGATIONImagine a software firm that is composed of different Business Units (or departments) like Storage BU, Networking BU. Automobile BU. The life time of these Business Units is governed by the lifetime of the organization. In other words, these Business Units cannot exist independently without the firm. This is COMPOSITION. (ie the firm is COMPOSED OF business units)The software firm may have external caterers serving food to the employees. These caterers are NOT PART OF the firm. However, they are ASSOCIATED with the firm. The caterers can exist even if our software firm is closed down. They may serve another firm! Thus the lifetime of caterers is not governed by the lifetime of the software firm. This is typical ASSOCIATIONConsider a Car manufacturing unit. We can think of Car as a whole entity and Car Wheel as part of the Car. (at this point, it may look like composition..hold on) The wheel can be created weeks ahead of time, and it can sit in a warehouse before being placed on a car during assembly. In this example, the Wheel class's instance clearly lives independently of the Car class's instance. Thus, unlike composition, in aggregation, life cycles of the objects involved are not tightly coupled.-----------------------------------------------------------------------------------------AssociationAssociation is a relationship where all object have their own lifecycle and there is no owner. Let’s take an example of Teacher and Student. Multiple students can associate with single teacher and single student can associate with multiple teachers but there is no ownership between the objects and both have their own lifecycle. Both can create and delete independently. Points:• Is a Relationship between objects.• Objects have independent lifecycles.

Page 7: Java

• There is no owner.• Objects can create and delete independently.

AggregationAggregation is a specialize form of Association where all object have their own lifecycle but there is ownership and child object can not belongs to another parent object. Let’s take an example of Department and teacher. A single teacher can not belongs to multiple departments, but if we delete the department teacher object will not destroy. We can think about “has-a” relationship.Points:• Specialize form of Association.• has-a relationship between objects• Object have independent life-cycles• Parent-Child relationshipCompositionComposition is again specialize form of Aggregation. It is a strong type of Aggregation. Child object dose not have their lifecycle and if parent object deletes all child object will also be deleted. Let’s take again an example of relationship between House and rooms. House can contain multiple rooms there is no independent life of room and any room can not belongs to two different house if we delete the house room will automatically delete. Let’s take another example relationship between Questions and options. Single questions can have multiple options and option can not belong to multiple questions. If we delete questions options will automatically delete.Points:• Specialize form of Aggregation• Strong Type of Aggregation.• Parent-Child relationship• Only parent object has independent life-cycle.

InterfacesAn interface is a collection of abstract methods. A class implements an interface, thereby inheriting the abstract methods of the interface.An interface is not a class. Writing an interface is similar to writing a class, but they are two different concepts. A class describes the attributes and behaviors of an object. An interface contains behaviors that a class implements.Unless the class that implements the interface is abstract, all the methods of the interface need to be defined in the class.

An interface is similar to a class in the following ways:An interface can contain any number of methods.An interface is written in a file with a .java extension, with the name of the interface matching the name of the file.The bytecode of an interface appears in a .class file.Interfaces appear in packages, and their corresponding bytecode file must be in a directory structure that matches the package name.

However, an interface is different from a class in several ways, including:You cannot instantiate an interface.An interface does not contain any constructors.All of the methods in an interface are abstract.An interface cannot contain instance fields. The only fields that can appear in an interface must be declared both static and final.An interface is not extended by a class; it is implemented by a class.An interface can extend multiple interfaces.

Page 8: Java

Declaring Interfaces:The interface keyword is used to declare an interface. Here is a simple example to declare an interface:Example:Let us look at an example that depicts encapsulation:

/* File name : NameOfInterface.java */import java.lang.*;//Any number of import statements

public interface NameOfInterface{ //Any number of final, static fields //Any number of abstract method declarations\}

Interfaces have the following properties:An interface is implicitly abstract. You do not need to use the abstract keyword when declaring an interface.Each method in an interface is also implicitly abstract, so the abstract keyword is not needed.Methods in an interface are implicitly public.Example:

/* File name : Animal.java */interface Animal {

public void eat();public void travel();

}

Implementing Interfaces:When a class implements an interface, you can think of the class as signing a contract, agreeing to perform the specific behaviors of the interface. If a class does not perform all the behaviors of the interface, the class must declare itself as abstract.A class uses the implements keyword to implement an interface. The implements keyword appears in the class declaration following the extends portion of the declaration.

/* File name : MammalInt.java */public class MammalInt implements Animal{

public void eat(){ System.out.println("Mammal eats"); }

public void travel(){ System.out.println("Mammal travels"); }

public int noOfLegs(){ return 0; }

public static void main(String args[]){ MammalInt m = new MammalInt(); m.eat(); m.travel(); }}

This would produce following result:

Mammal eatsMammal travels

Page 9: Java

When overriding methods defined in interfaces there are several rules to be followed:Checked exceptions should not be declared on implementation methods other than the ones declared by the interface method or subclasses of those declared by the interface method.The signature of the interface method and the same return type or subtype should be maintained when overriding the methods.An implementation class itself can be abstract and if so interface methods need not be implemented.When implementation interfaces there are several rules:A class can implement more than one interface at a time.A class can extend only one class, but implement many interface.An interface itself can extend another interface. An interface cannot implement another interface.Extending Interfaces:An interface can extend another interface, similarly to the way that a class can extend another class. The extends keyword is used to extend an interface, and the child interface inherits the methods of the parent interface.The following Sports interface is extended by Hockey and Football interfaces.

//Filename: Sports.javapublic interface Sports{ public void setHomeTeam(String name); public void setVisitingTeam(String name);}

//Filename: Football.javapublic interface Football extends Sports{ public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter);}

//Filename: Hockey.javapublic interface Hockey extends Sports{ public void homeGoalScored(); public void visitingGoalScored(); public void endOfPeriod(int period); public void overtimePeriod(int ot);}

The Hockey interface has four methods, but it inherits two from Sports; thus, a class that implements Hockey needs to implement all six methods. Similarly, a class that implements Football needs to define the three methods from Football and the two methods from Sports.Extending Multiple Interfaces:A Java class can only extend one parent class. Multiple inheritance is not allowed. Interfaces are not classes, however, and an interface can extend more than one parent interface.The extends keyword is used once, and the parent interfaces are declared in a comma-separated list.For example, if the Hockey interface extended both Sports and Event, it would be declared as:

public interface Hockey extends Sports, Event

Tagging or Marker Interfaces:The most common use of extending interfaces occurs when the parent interface does not contain any methods. For example, the MouseListener interface in the java.awt.event package extended java.util.EventListener, which is defined as:

package java.util;public interface EventListener{}

Page 10: Java

An interface with no methods in it is referred to as a tagging interface. There are two basic design purposes of tagging interfaces:Creates a common parent: As with the EventListener interface, which is extended by dozens of other interfaces in the Java API, you can use a tagging interface to create a common parent among a group of interfaces. For example, when an interface extends EventListener, the JVM knows that this particular interface is going to be used in an event delegation scenario.Adds a data type to a class: This situation is where the term tagging comes from. A class that implements a tagging interface does not need to define any methods (since the interface does not have any), but the class becomes an interface type through polymorphism.

Page 11: Java

The Collection Interfaces:A collections framework is a unified architecture for representing and manipulating collections. Collections frameworks contain the following:Interfaces: These are abstract data types that represent collections. Interfaces allow collections to be manipulated independently of the details of their representation. In object-oriented languages, interfaces generally form a hierarchy.Implementations i.e. Classes: These are the concrete implementations of the collection interfaces. In essence, they are reusable data structures.Algorithms: These are the methods that perform useful computations, such as searching and sorting, on objects that implement collection interfaces. The algorithms are said to be polymorphic: that is, the same method can be used on many different implementations of the appropriate collection interface.In addition to collections, the framework defines several map interfaces and classes. Maps store key/value pairs. Although maps are not collections in the proper use of the term, but they are fully integrated with collections.The Collection Interfaces:

The collections framework defines several interfaces. This section provides an overview of each interface:SN Interfaces with Description

1 The Collection InterfaceThis enables you to work with groups of objects; it is at the top of the collections

hierarchy.

2 The List Interface

This extends Collection and an instance of List stores an ordered

collection of elements.3 The Set

This extends Collection to handle sets, which must contain unique

elements4 The SortedSet

This extends Set to handle sorted sets5 The Map

This maps unique keys to values.

Page 12: Java

6 The Map.Entry

This describes an element (a key/value pair) in a map.

This is an inner class of Map.

7 The SortedMap

This extends Map so that the keys are maintained in ascending

order.8 The Enumeration

This is legacy interface and defines the methods by which you can enumerate (obtain one at a time) the elements in a collection of objects. This legacy interface has been superceded by Iterator.

The Collection Classes:Java provides a set of standard collection classes that implement Collection interfaces. Some of the classes provide full implementations that can be used as it is and others are abstract class, providing skeletal implementations that are used as starting points for creating concrete collections.

The standard collection classes are summarized in the following table:SN Classes with Description

1 AbstractCollection Implements most of the Collection interface.

2 AbstractList Extends AbstractCollection and implements most of the List interface.

3 AbstractSequentialList Extends AbstractList for use by a collection that uses sequential rather than random access of its elements.

4 LinkedList  

Implements a linked list by extending

AbstractSequentialList.5 ArrayList  

Implements a dynamic array by extending AbstractList.

Page 13: Java

6 AbstractSet Extends AbstractCollection and implements most of the Set interface.

7 HashSet  

Extends AbstractSet for use with a hash table.

8 LinkedHashSet  

Extends HashSet to allow insertion-order iterations.

9 TreeSet  

Implements a set stored in a tree. Extends AbstractSet.

10 AbstractMap Implements most of the Map interface.

11 HashMap  

Extends AbstractMap to use a hash table.

12 TreeMap  

Extends AbstractMap to use a tree.

13WeakHashMap  

Extends AbstractMap to use a hash table with weak

keys.

14 LinkedHashMap  

Extends HashMap to allow insertion-order iterations.

15 IdentityHashMap   Extends AbstractMap and uses reference equality when comparing documents.

Page 14: Java

The AbstractCollection, AbstractSet, AbstractList, AbstractSequentialList and AbstractMap classes provide skeletal implementations of the core collection interfaces, to minimize the effort required to implement them.

Comparator and Comparable in Java ExamplesWhat is Difference between Comparator and Comparable in Java question was asked in a Test paper for one of big Investment bank first round of interview. It was not that straight forward but it was related to how you will sort Employee object based on his EmployeeID and his name and that involves the use of both Comparable and Comparator in Java.Comparators and comparable in Java are two of fundamental interface of Java API which is very important to understand to implement sorting in Java. It’s often required to sort objects stored in any collection class or in Array and that time we need to use compare () and compareTo () method defined in java.util.Comparator and java.lang.Comparable class. Let’s see some important points about both Comparable and Comparator in Java before moving ahead

Difference between Comparator and Comparable in Java1) Comparator in Java is defined in java.util package while Comparable interface in Java is defined in java.lang package.

2) Comparator interface in Java has method public int compare (Object o1, Object o2)which returns a negative integer, zero, or a positive integer as the first argument isless than, equal to, or greater than the second. While Comparable interface has method

public int compareTo(Object o)which returns a negative integer, zero, or a positive integer as this object is lessthan, equal to, or greater than the specified object.

3) If you see then logical difference between these two is Comparator in Java compare two objects provided to him, while Comparable interface compares "this" reference with the object specified.

4) Comparable in Java is used to implement natural ordering of object. In Java API String, Date and wrapper classes implement Comparable interface.

5) If any class implement Comparable interface in Java then collection of that object either List or Array can be sorted automatically by using Collections.sort() or Arrays.sort() method and object will be sorted based on there natural order defined by CompareTo method.

6)Objects which implement Comparable in Java can be used as keys in a sorted map or elements in a sorted set for example TreeSet, without specifying any Comparator.

Example of using Comparator and Comparable in Java

So in Summary if you want to sort based on natural order or object then use Comparable in Java and if you want to sort on some other attribute of object then Comparator in Java is the way to go. Now to understand these concepts lets see an example

1) There is class called Person, sort the Person based on person_id.2) Sort the Person based on Name.

Page 15: Java

For a Person class sorting based on person_id can be treated as natural order sorting and sorting based on Name can be implemented using Comparator interface. To sort based on person_id we need to implement compareTo() method.

public class Person implements Comparable { private int person_id; private String name; /** * Compare current person with specified person return zero if person_id for both person is same return negative if current person_id is less than specified one return positive if specified person_id is greater than specified one */ public int compareTo(Person o) { return this.person_id - o.person_id ; } ….}

And for sorting based on person name we can implement compare (Object o1, Object o2) method of Comparator in Java or Java Comparator class.

public class PersonSortByPerson_ID implements Comparator{

public int compare(Person o1, Person o2) { return o1.getPersonId() - o2.getPersonId(); }}

You can write several types of Java Comparator based upon your need for example reverseComparator , ANDComparator , ORComparator etc which will return negative or positive number based upon logical results.

How to Compare String in JavaFor comparing String in Java we should not be worrying because String implements Comparable interface in Java and provides implementation for CompareTo method which Compare two strings based on characters inside or you can say in lexical order. You just need to call String.compareTo(AnotherString) and Java will determine whether specified String is greater than , equal to or less than current String. String is also immutable in Java an important property to remember.

How to Compare Dates in JavaDates are represented by java.util.Date class in Java and like String Dates also implements Comparable in Java so they will be automatically sorted based on there natural ordering if they got stored in any sorted collection like TreeSet or TreeMap. If you explicitly wants to compare two dates in Java you can call Date.compareTo(AnotherDate) method in Java and it will tell whether specified date is greater than , equal to or less than current String.

package examples; /*Java Comparator example.This Java Comparator example describes how java.util.Comparatorinterface is implemented to compare Java custom class objects. This Java Comparator is passed to Collection's sorting method(for example Collections.sort method) to perform sorting of Java customclass objects.

Page 16: Java

*/ import java.util.*; /*java.util.Comparator interface declares two methods,1) public int compare(Object object1, Object object2) and2) boolean equals(Object object)*/ /*We will compare objects of the Employee class using custom comparatorson the basis of employee age and name.*/ class Employee{ private int age; private String name; public void setAge(int age){ this.age=age; } public int getAge(){ return this.age; } public void setName(String name){ this.name=name; } public String getName(){ return this.name; }} /*User defined Java comparator.To create custom java comparator, implement Comparator interface anddefine compare method. The below given comparator compares employees on the basis of their age.*/ class AgeComparator implements Comparator{ public int compare(Object emp1, Object emp2){ /* * parameter are of type Object, so we have to downcast it to Employee objects */ int emp1Age = ((Employee)emp1).getAge(); int emp2Age = ((Employee)emp2).getAge(); if(emp1Age > emp2Age) return 1; else if(emp1Age < emp2Age) return -1; else return 0; } }

Page 17: Java

/*The below given comparator compares employees on the basis of their name.*/ class NameComparator implements Comparator{ public int compare(Object emp1, Object emp2){ //parameter are of type Object, so we have to downcast it to Employee objects String emp1Name = ((Employee)emp1).getName(); String emp2Name = ((Employee)emp2).getName(); //uses compareTo method of String class to compare names of the employee return emp1Name.compareTo(emp2Name); } } /*This Java comparator example compares employees on the basis of their age and name and sort them in that order.*/ public class JavaComparatorExample{ public static void main(String args[]){ //Employee array which will hold employees Employee employee[] = new Employee[2]; //set different attributes of the individual employee. employee[0] = new Employee(); employee[0].setAge(40); employee[0].setName("Joe"); employee[1] = new Employee(); employee[1].setAge(20); employee[1].setName("Mark"); System.out.println("Order of employee before sorting is"); for(int i=0; i < employee.length; i++){ System.out.println( "Employee " + (i+1) + " name :: " + employee[i].getName() + ", Age :: " + employee[i].getAge()); } /* Sort method of the Arrays class sorts the given array. Signature of the sort method is, static void sort(Object[] object, Comparator comparator) IMPORTANT: All methods defined by Arrays class are static. Arrays class serves as a utility class. */ //Sorting array on the basis of employee age by passing AgeComparator

Page 18: Java

Arrays.sort(employee, new AgeComparator()); System.out.println("\n\nOrder of employee after sorting by employee age is"); for(int i=0; i < employee.length; i++){ System.out.println( "Employee " + (i+1) + " name :: " + employee[i].getName() + ", Age :: " + employee[i].getAge()); } //Sorting array on the basis of employee Name by passing NameComparator Arrays.sort(employee, new NameComparator()); System.out.println("\n\nOrder of employee after sorting by employee name is"); for(int i=0; i < employee.length; i++){ System.out.println( "Employee " + (i+1) + " name :: " + employee[i].getName() + ", Age :: " + employee[i].getAge()); } } } /*OUTPUT of the above given Java Comparable Example would be :Order of employee before sorting isEmployee 1 name :: Joe, Age :: 40Employee 2 name :: Mark, Age :: 20Order of employee after sorting by employee age isEmployee 1 name :: Mark, Age :: 20Employee 2 name :: Joe, Age :: 40Order of employee after sorting by employee name isEmployee 1 name :: Joe, Age :: 40Employee 2 name :: Mark, Age :: 20*/

/*Java Comparable example.This Java Comparable example describes how java.util.Comparableinterface is implemented to compare user defined classe's objects.*/ import java.util.*; /*Comparable interface is used to make user defined class's objects comparable.This interface declares one method compareTo(Object object)and determines how objects can be compared to with each other.*/ /*Implement java.util.Comparable interface to make class objects comparable.*/ class Employee implements Comparable{ private int age; public void setAge(int age){ this.age=age; } public int getAge(){ return this.age;

Page 19: Java

} /* Signature of compareTo method is, public int compareTo(Object object). compareTo method should return 0 if both objects are equal, 1 if first grater than other and -1 if first less than the other object of the same class. */ public int compareTo(Object otherEmployee){ // If passed object is of type other than Employee, throw ClassCastException. if(!(otherEmployee instanceof Employee)){ throw new ClassCastException("Invalid object"); } int age = ((Employee) otherEmployee).getAge(); if(this.getAge() > age) return 1; else if ( this.getAge() < age ) return -1; else return 0; } } public class JavaComparableExample{ public static void main(String args[]){ /* Create two different Employee objects, so that we can compare them. */ Employee one = new Employee(); one.setAge(40); Employee two = new Employee(); one.setAge(30); /* Use compareTo method to determine which employee is younger */ if(one.compareTo(two) > 0) { System.out.println("Employee one is elder than employee two!"); } else if(one.compareTo(two) < 0) { System.out.println("Employee one is younger than employee two!"); } else if(one.compareTo(two) == 0) { System.out.println("Both employees are same!"); } } } /*OUTPUT of the above given Java Comparable Example would be:Employee one is elder than employee two!*/

Page 20: Java

Usage of equals and hascode methodsIntroductionJava.lang.Object has methods called hasCode() and equals(). These methods play a significant role in the real time application. However its use is not always common to all applications. In some case these methods are overridden to perform certain purpose. In this article I will explain you some concept of these methods and why it becomes necessary to override these methods.hashCode()As you know this method provides the has code of an object. Basically the default implementation of hashCode() provided by Object is derived by mapping the memory address to an integer value. If look into the source of Object class , you will find the following code for the hashCode.public native int hashCode();It indicates that hashCode is the native implementation which provides the memory address to a certain extent. However it is possible to override the hashCode method in your implementation class.equals()This particular method is used to make equal comparison between two objects. There are two types of comparisons in Java. One is using “= =” operator and another is “equals()”. I hope that you know the difference between this two. More specifically the “.equals()” refers to equivalence relations. So in broad sense you say that two objects are equivalent they satisfy the “equals()” condition. If you look into the source code of Object class you will find the following code for the equals() method.

public boolean equals(Object obj) {

return (this == obj);}

Now I will explain you when to override the equals() and hashCode() methods and why it is necessary to override these methods. In this regard there is a rule of thumb that if you are going to override the one of the methods( ie equals() and hashCode() ) , you have to override the both otherwise it is a violation of contract made for equals() and hashCode(). Please refer to the Sun’s java docs for the method’s contract. I provide some test case scenario where you will find the significance of these methods.Case-1:You can override the hashCode method in your own way. Please refer to the following example.

package com.ddlab.core;

public class Emp {

private int age ;

public Emp( int age ){

super();this.age = age;

}

public int hashCode(){

return age;}

}

In the above example class “Emp” the variable age is the significant factor. Here the hashCode value will return the age of the person. Now let us consider the following test harness class.

Page 21: Java

package com.ddlab.core;

public class TestEmp{

public static void main(String[] args) {

Emp emp1 = new Emp(23);System.out.println("emp1.hashCode()--->>>"+emp1.hashCode());

}}If you run the above program, the output will be the age what you have given i.e. 23.Now question arises whether there is any way we can get the original hashCode(). We can say that if we do not override the hashCode() method what could have been the hashCode of this object. However please do not feel depressed, Java provide another approach even if you have overridden the hashCode() method , still you can get the original hashCode of a particular class. Now run the following test harness program.

package com.ddlab.core;

public class TestEmp{

public static void main(String[] args) {

Emp emp1 = new Emp(23);System.out.println("Overridden hashCode()--->>>"+emp1.hashCode());int originalHashCode = System.identityHashCode(emp1);System.out.println("Original hashCode of Emp---->>>"+originalHashCode);

}}

Here the output will be like thisOverridden hashCode()--->>>23Original hashCode of Emp---->>>8567361As you know the above number is arbitrary, it depends upon your system.So then why it is necessary to override this method. There is one reason that if want to compare two objects based upon the equals() method. Although in a very simple class like “Emp”, you can achieve without overriding hashCode() method. But if you do this , you are going to violate the contract for the methods hashCode() and hashCode() of the object class. The similar case is for the method equals(). So funcational point is that if want to compare two objects based upon the equals() method you have to override both hashCode() and equals() methods. Please have look into the Emp class with the overridden methods and the related test harness class.

package com.ddlab.core;

public class Emp {

private int age ;

public Emp( int age ){

super();this.age = age;

}

public int hashCode(){

return age;

Page 22: Java

}

public boolean equals( Object obj ){

boolean flag = false;Emp emp = ( Emp )obj;if( emp.age == age )

flag = true;return flag;

}}

The related test harness class is given below.

package com.ddlab.core;

public class TestEmp{

public static void main(String[] args) {

Emp emp1 = new Emp(23);Emp emp2 = new Emp(23);System.out.println("emp1.equals(emp2)--->>>"+emp1.equals(emp2));

}}

Case- 2Think of a test scenario where you want to store your objects in a HasSet and you want to find a particular object. First let us see if we do not override the methods and we want to store the objects in the HashSet. Let us analyse the impact of it from the following code.

package com.ddlab.core;

public class Emp {

private int age ;

public Emp( int age ){

super();this.age = age;

}

}

In the above code it is a normal class. Now let us see the test harness class.

package com.ddlab.core;

import java.util.HashSet;

public class TestEmp{

public static void main(String[] args) {

Emp emp1 = new Emp(23);

Page 23: Java

Emp emp2 = new Emp(24);Emp emp3 = new Emp(25);Emp emp4 = new Emp(26);Emp emp5 = new Emp(27);HashSet<Emp> hs = new HashSet<Emp>();hs.add(emp1);hs.add(emp2);hs.add(emp3);hs.add(emp4);hs.add(emp5);

System.out.println("HashSet Size--->>>"+hs.size());System.out.println("hs.contains( new Emp(25))--->>>"+hs.contains(new Emp(25)));System.out.println("hs.remove( new Emp(24)--->>>"+hs.remove( new Emp(24));System.out.println("Now HashSet Size--->>>"+hs.size());

}}If you run the above program, the will output will be like the following.HashSet Size--->>>5hs.contains( new Emp(25))--->>>falsehs.remove( new Emp(24)--->>>falseNow HashSet Size--->>>5It means that you can not find the object. However it is not the case for Integer object. You can put object of type Integer in a HashSet and you can try and you can see the effect. Now let us modify the “Emp” class so that we will get over the problems what we faced in the above test harness class.

package com.ddlab.core;

public class Emp {

private int age ;

public Emp( int age ){

super();this.age = age;

}

public int hashCode(){

return age;}

public boolean equals( Object obj ){

boolean flag = false;Emp emp = ( Emp )obj;if( emp.age == age )

flag = true;return flag;

}}

Page 24: Java

Here in the above class, we have overridden the hashCode() and equals() methods. Now if you run the same test harness class, you will get the desired output like the following.HashSet Size--->>>5hs.contains( new Emp(25))--->>>truehs.remove( new Emp(24))--->>>trueNow HashSet Size--->>>4Case – 3In this case you want to use your object as key not the value in the HashMap. So you have to override both the methods hashCode() and equals(). However it is left to the reader to create the object and test the feature in a Map.Case-4If want to make your own immutable object , it will be wiser to override the equals() and hashCode() methods.

String equals() and hashcode()The equals method in String class is overridden so as to check logical equality of Strings. The String equals() method does not however check for referential equality as done with == operator. Thus even if two different String objects with same contents are

compared using the equals() method, the result will be true.

The hashcode will also be same for two different String objects with same contents. Thus

means that the String class maintains the equals-hashcode contract.

So when we write a piece of code like this:

String str1 = new String("abc");String str2 = new String("abc");String str3 = new String("123");String str4 = new String("456");HashMap hm = new HashMap();hm.put(str1,str3);hm.put(str2,str4);System.out.println(hm.get(str1));System.out.println(hm.get(str2)); Output:456456

We notice that in the above code, instead of creating two entries for the same hashcode,

the earlier entry “123″ is replaced by the second “456″in the hashmap.

This happened because of the equals method. The hashcode for str1 and str2 was calculated

to be same. When storing value object for key str2, equals was used to determine whether

to replace the value object corresponding to str1 or to use bucketing.

Since String equals() method made str1 and str2 equal so the value object corresponding to str1 was replaced with new value object which the program wanted to store

against key str2.

Now if String equals() method had checked for referential equality, then there would be

two value objects stored corresponding to the two keys str1 and str2.

Page 25: Java

A developer which is not aware of the fact that equals method doesn’t check for

referential equality would keep on debugging his program for the unexpected results he

gets.

Though there is nothing wrong with the equals method of String class but the user of

String API should be aware of the fact.

The basics: override hashCode() and equals()

Put very simply, there are two methods that a class needs to override to make objects of that class work as hash map keys:

public int hashCode();public boolean equals(Object o);

As you might expect, the hashCode() method is where we put our hash function. Hash functions such as those mentioned in our hash function guidelines can generally be slotted

in. Note that HashMap will not do any extra caching of the hash code. So if calculating the hash is relatively expensive (as in the case of String) it may be worth explicitly caching the hash code.

The equals() method

The equals() method must return true if the fields of the current object equal those of the object passed in, else return false. By "equal", we generally mean that primitive fields

match via the == operator, and objects are either both null or both non-null and match via the equals() method. Note two important constraints onequals():

if x.equals(y) returns true, then the hash codes of x and y must be identical; it must be reflexive and transitive: that is, x.equals(y) must return the same value

as y.equals(x), and if x.equals(y) and y.equals(z), thenx.equals(z) must also be true (see below for what this actually means in real terms!).

The first of these is generally common sense given that the purpose of a hash function is to "narrow down a search" which will ultimately be performed using theequals() to perform the final check for a match. The second is more or less common sense, but it does mean, for example, that we can't allow a null reference to equal an "empty" object. It also means, strictly speaking, that a subclass cannot add new variable comparisons to the equals() method2.

Example

Now let's see an example. We'll look at a simple class that encapsulates a pair of screen coordinates. We assume that individually, the X and Y coordinates are essentially random, but that the maximum coordinate in each case will be in the order of a couple of thousand (in other words will have about 10 or 11 bits of randomness). So to make the hash code, we pick a number that is roughly halfway between these bits, then find a prime (or at worst odd) number that is close to 211. Our old favourite of 31 (=25-1) will do us fine.

The equals() method is trivial, but note the convention of returning false if the object passed in isn't of a compatible type.

public class CoordinatePair { private int x, y; public int hashCode() { return (x * 31) ^ y;

Page 26: Java

} public boolean equals(Object o) { if (o instanceof CoordinatePair) { CoordinatePair other = (CoordinatePair) o; return (x == other.x && y == other.y); } return false; }}

1. I think this convention predates Java 5 generics: arguably, we really don't expect a

case where equals() will be called against an object of an incompatible type and should just apply the case an rely on the resulting runtime exception if the cast fails.2. The problem with subclassing can be explained with a quick example. Suppose we

extend Rectangle (whose equals() method effectively compares its co-ordinates and dimensions, although via the Rectangle2D base class) to make a class called ColouredRectangle, whose equals() method returns true if and only if the colours of the rectangles are identical. Now we have the problem that a plain Rectangle, if passed a ColouredRectangle to its equals() method, would return true provided the co-ordinates and dimensions were the same, discounting the colour; whereas the other way

round, ColouredRectangle.equals() would always return false (because it wasn't comparing against another ColouredRectangle).