Sie sind auf Seite 1von 26

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 classs 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()); } }

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.

Inheritance
Inheritance 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 Animal Reptile IS-A Animal Dog IS-A Mammal Hence : Dog IS-A Animal as well With 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 true true

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: true true true 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{} However a class can implement one or more interfaces. This has made Java get rid of the impossibility of multiple inheritance.

Polymorphism
Polymorphism 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 Animal A Deer IS-A Vegetarian A Deer IS-A Deer A Deer IS-A Object When 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); } 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) { 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 Employee Constructing an Employee Call mailCheck using Salary reference -Within mailCheck of Salary class Mailing check to Mohd Mohtashim with salary 3600.0 Call mailCheck using Employee reference-Within mailCheck of Salary class Mailing 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 AGGREGATION


Imagine 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 ASSOCIATION Consider 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. ----------------------------------------------------------------------------------------Association Association is a relationship where all object have their own lifecycle and there is no owner. Lets 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. There is no owner. Objects can create and delete independently. Aggregation Aggregation 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. Lets 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 relationship Composition Composition 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. Lets 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. Lets 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.

Interfaces
An 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.

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 eats Mammal travels

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.java public interface Sports { public void setHomeTeam(String name); public void setVisitingTeam(String name); } //Filename: Football.java public interface Football extends Sports { public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); } //Filename: Hockey.java public 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 commaseparated 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 {} 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.

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 1 Interfaces with Description The Collection Interface This enables you to work with groups of objects; it is at the top of the collections

Collection Interface

hierarchy. 2 The List Interface This extends Collection and an instance of

List stores an ordered

List Interface

collection
3 The Set

of elements.

This extends Collection to handle

sets,

which

must contain unique

Set Interface

elements
4 The SortedSet

Sorted Set

This extends Set 5 The Map

to handle sorted sets

Map Interface

This

maps unique keys to values.

The Map.Entry This

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

Map.Entry Interface

This is an inner class of Map. 7 The SortedMap This extends Map so that the

keys are maintained in ascending

SortedMap Interface

order.
8 The Enumeration

enumerate (obtain one at a time) the elements in a collection


This is legacy interface and defines the methods by which you can

of objects.

This legacy interface has been superceded by Iterator.

Enumeration Interface

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 1 2 3 Classes with Description AbstractCollection Implements most of the Collection interface. AbstractList Extends AbstractCollection and implements most of the List interface. AbstractSequentialList Extends AbstractList for use by a collection that uses sequential rather than random access of its elements. LinkedList

Implements a linked list by extending


Linked List

AbstractSequentialList.
5 ArrayList

Implements a dynamic array by extending AbstractList.


Array List

AbstractSet Extends AbstractCollection and implements most of the Set interface.

HashSet

Extends AbstractSet for use with a hash table.


Hash Set

LinkedHashSet

Linked HashSet

Extends HashSet to allow insertion-order iterations. 9 TreeSet

Tree Set

Implements a set stored in a tree. Extends AbstractSet. 10 11 AbstractMap Implements most of the Map interface. HashMap

Hash Map

Extends AbstractMap to use a hash table. 12 TreeMap

Tree Map

Extends AbstractMap to use a tree. 13 WeakHashMap

Extends AbstractMap to use a hash table with weak


Weak Hash Map

keys.
14 LinkedHashMap

Linked Hash Map

Extends HashMap to allow insertion-order iterations. 15 IdentityHashMap Extends AbstractMap and uses reference equality when comparing documents.

Identity Hash Map

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 Examples


What 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. Its 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. Lets see some important points about both Comparable and Comparator in Java before moving ahead Difference between Comparator and Comparable in Java 1) 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 is less 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 less than, 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. 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 Java For 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 Java Dates 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.Comparator interface 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 custom class objects. */ import java.util.*; /* java.util.Comparator interface declares two methods, 1) public int compare(Object object1, Object object2) and 2) boolean equals(Object object) */ /*

We will compare objects of the Employee class using custom comparators on 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 and define 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;

} }

/* 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 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 is Employee 1 name :: Joe, Age :: 40 Employee 2 name :: Mark, Age :: 20 Order of employee after sorting by employee age is Employee 1 name :: Mark, Age :: 20 Employee 2 name :: Joe, Age :: 40 Order of employee after sorting by employee name is Employee 1 name :: Joe, Age :: 40 Employee 2 name :: Mark, Age :: 20 */ /* Java Comparable example. This Java Comparable example describes how java.util.Comparable interface 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; } /* 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! */

Usage of equals and hascode methods


Introduction Java.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 Suns java docs for the methods 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.

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 this Overridden hashCode()--->>>23 Original hashCode of Emp---->>>8567361 As 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; } 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- 2 Think 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); 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--->>>5 hs.contains( new Emp(25))--->>>false hs.remove( new Emp(24)--->>>false Now HashSet Size--->>>5 It 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; } }
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--->>>5 hs.contains( new Emp(25))--->>>true hs.remove( new Emp(24))--->>>true Now HashSet Size--->>>4 Case 3

In this case you want to use your object as to override both the methods hashCode() and create the object and test the feature in a Case-4 If want to make your own immutable object , hashCode() methods.

key not the value in the HashMap. So you have equals(). However it is left to the reader to Map. it will be wiser to override the equals() and

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: 456 456

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 456in 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. A developer which is not aware of the fact that equals method doesnt 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; } 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).

Das könnte Ihnen auch gefallen