Nov 12, 2010

Encapsulation, Loose coupling and HAS-A relation ship in Java

Encapsulation in an OOP sense generally aims to guide (or force) users of your components to use your classes correctly and makes it harder to abuse the class's functionality by hiding the implementation. Encapsulation allows an object to separate its interface from its implementation. The data and the implementation code for the object are hidden behind its interface. For example, in Java, we have pre defined libraries, and we use them, but, we don't know how does the internal implementation of a Class. We simply use the public method as the interface to access the object.

"Loose coupling" is not a coding issue, it's a design issue. Loose coupling simply means that individual design elements should be constructed so the amount of unnecessary information they need to know about other design elements are reduced. In short, loose coupling is a design goal that seeks to reduce the interdependencies between components of a system with the goal of reducing the risk that changes in one component will require changes in any other component.

The degree of coupling between two components can be qualitatively measured by determining the effects of changing the contract or interface between two components or systems. For example:

* What would happen if you added or deleted a property from a class?
* What would happen if you changed the data type of a column in a table?
* What would happen if you added a column to a table?
* What would happen if you changed you asynchronous email component?
* What would happen if your database server changed from SQL Server to mySQL or Oracle?

The degree of pain that each of these changes would cause you is a good qualitative measurement of how tightly coupled your components are to the components they depend on.

interface Bounceable {}

class Car implements Bounceable {}
class Ball implements Bounceable {}

public class TestCoupling {
 Car c;// tight coupling
 Bounceable b; // loose coupling.

With the Bounceable reference, we can have a Car instance or a Ball instance. So, the TestCoupling and the Car or Ball are loosely coupled(without the Car reference).

Nov 2, 2010

Instance initializers in Java

The body of a class declares members (fields and methods and nested classes and interfaces), instance and static initializers, and constructors. At the beginning of an object's life, the Java virtual machine (JVM) allocates enough memory on the heap to accommodate the object's instance variables. When that memory is first allocated, however, the data it contains is unpredictable. If the memory were used as is, the behavior of the object would also be unpredictable. To guard against such a scenario, Java makes certain that memory is initialized, at least to predictable default values, before it is used by any code.

Initialization is important because, historically, uninitialized data has been a common source of bugs. Bugs caused by uninitialized data occur regularly in C, for example, because it doesn't have built-in mechanisms to enforce proper initialization of data. C programmers must always remember to initialize data after they allocate it and before they use it. The Java language, by contrast, has built-in mechanisms that help you ensure proper initialization of the memory occupied by a newly-created object. With proper use of these mechanisms, you can prevent an object of your design from ever being created with an invalid initial state.

The Java language has three mechanisms dedicated to ensuring proper initialization of objects: instance initializers (also called instance initialization blocks), instance variable initializers, and constructors. (Instance initializers and instance variable initializers collectively are called "initializers.") All three mechanisms result in Java code that is executed automatically when an object is created. When you allocate memory for a new object with the new operator or the newInstance() method of class Class, the Java virtual machine will insure that initialization code is run before you can use the newly-allocated memory. If you design your classes such that initializers and constructors always produce a valid state for newly-created objects, there will be no way for anyone to create and use an object that isn't properly initialized.

And, when the object is created in Java, there is an order to initialize the object.
1. Set fields to default initial values (0, false, null)
2. Call the constructor for the object (but don't execute the body of the constructor yet)
3. Invoke the constructor of the superclass
4. Initialize fields using initializers and initialization blocks
5. Execute the body of the constructor

Let's have some samples.
public class InstanceInitializers1 {
 int i = 10;
  i = 8;

 public static void main(String[] args) {
  new InstanceInitializers1();
As you all expected, the output is 10.

Java 1.1 introduced the instance initializer, which is also called the instance initialization block. Instance initializers are a useful alternative to instance variable initializers whenever:
(1) initializer code must catch exceptions, or
(2) perform fancy calculations that can't be expressed with an instance variable initializer.
You could, of course, always write such code in constructors. But in a class that had multiple constructors, you would have to repeat the code in each constructor. With an instance initializer, you can just write the code once, and it will be executed no matter what constructor is used to create the object. Instance initializers are also useful in anonymous inner classes, which can't declare any constructors at all.

The code inside an instance initializer may not return. Except in the case of anonymous inner classes, an instance initializer may throw checked exceptions only if the checked exceptions are explicitly declared in the throws clause of every constructor in the class. Instance initializers in anonymous inner classes, on the other hand, can throw any exception. When you write an initializer (either an instance variable initializer or instance initializer), you must be sure not to refer to any instance variables declared textually after the variable being initialized. In other words, you can't make a forward reference from an initializer. If you disobey this rule, the compiler will give you an error message and refuse to generate a class file. When an object is created, initializers are executed in textual order -- their order of appearance in the source code. This rule helps prevent initializers from using instance variables that have yet to be properly initialized.

Even though, the instance variable are get initialized with the default values(as indicated above) before the initialization block runs, we can't make forward reference. If you disobey this rule, the compiler will give you an error message and refuse to generate a class file. For example,
public class InstanceInitializers2 {
  i = 8;
 int i = 10;

 public static void main(String[] args) {
  new InstanceInitializers1();
The above code won't compile because of forward referencing. But, with the below code snaps, you can see the forward referencing and initializing with the default values.
public class Initializers1 {
 int j = getI();
 int i = 10;

 public static void main(String[] args) {
  System.out.println(new Initializers1().j);
 public int getI() {
  return i;
What do you expecting as output? The value 0 will be printed. Because, when the getI() method is invoked, the value of i is 0(the default value).

The instance initializer block can throw exceptions, but, every constructor of the class should declare to throw that exception or one of its super exception. Let's have a example.

public class InitializerException {
  if(true) {
   throw new FileNotFoundException();//A checked exception

 public InitializerException() throws FileNotFoundException {

 public static void main(String[] args) throws Exception {
  new InitializerException();
This is from the JLS,

It is a compile-time error if an instance initializer cannot complete normally. It is compile-time error if an instance initializer of a named class can throw a checked exception unless that exception or one of its supertypes is explicitly declared in the throws clause of each constructor of its class and the class has at least one explicitly declared constructor. An instance initializer in an anonymous class can throw any exceptions.
And, we need a if(true) { code snaps because, it's said that, "A break, continue, return, or throw statement cannot complete normally" so we used it escape it.

Oct 11, 2010

Hash Function Algorithms and Java hashCode() method and HashMap.

Hash functions are by definition and implementation, pseudo random number generators. In general there is a theoretical hash function known as the perfect hash function for any group of data. The perfect hash function by definition states that no collisions will occur meaning no repeating hash values will arise from different elements of the group. In reality its very difficult to find a perfect hash function and the practical applications of perfect hashing and its variant minimal perfect hashing are quite limited. In practice it is generally recognized that a perfect hash function is the hash function that produces the least amount of collisions for a particular set of data. 

Fast table lookup can be implemented using a hash function and a hash table. Elements are found in the hash table by calculating the hash of the element's key and using the hash value as the index into the table. This is clearly faster than other methods, such as examining each element of the table sequentially to find a match. And also, other than this, there are some other usages of the hash function generally, such as, encrypting a message to unreadable by third parties in Cryptography, etc.

In Java, A common hashing scheme uses an array where each element is a list of items. The array elements are called buckets. Operations in a hashing scheme involve computing an arrayindex from an item. Converting an item to its array index is done by a hash function The array index returned by the hash function is called the hash value of the item. The hash value identifies a particular bucket. Storing an item involves the following steps:
1. Hashing the item to determine the bucket.
2. If the item does not match one already in the bucket, it is stored in the bucket.
Note that no duplicate items are stored. Retrieving an item is based on using a key. The key represents the identity of the item. Item retrieval is also a two-step process:
1. Hashing the key to determine the bucket.
2. If the key matches an item in the bucket, this item is retrieved from the bucket.
Different items can hash to the same bucket, meaning that the hash function returns the same hash value for these items. This condition is called a collision. The list maintained by a bucket contains the items that hash to the bucket.
The hash value only identifies the bucket. Finding an item in the bucket entails a search and requires an equality function to compare items. The items maintained in a hash-based storage scheme must, therefore, provide two essential functions: a hash function and an equality function. The performance of a hashing scheme is largely affected by how well the hash function distributes a collection of items over the available buckets. A hash function should not be biased toward any particular hash values. An ideal hash function produces a uniform distribution of hash values for a collection of items across all possible hash values. Such a hash function is not an easy task to design. Fortunately, heuristics exist for constructing adequate hash functions.