Category: Core Java


Abstract Class Vs Interface

Yes, I do understand the title reflects the age old repetitive interview question. It has been asked again, again and again and then just some more times. But why, why is this so important. Why does every software company on the planet has the question sticking out of their heads. We all know the answer to this(duh??), they all know the answer to this(duh??), and nearly every preparation site answers this, then what is the big fuss about?

Well, the fantastic thing about an iceberg is its tip and then comes in the total size. In a very similar fashion, for this question, everybody understands the syntax but fails to understand the semantics. If you have been reading about this, few well know answers are:

  • Interface is a 100% abstract class
  • Java class(es) can implement multiple interfaces but it can extend only one abstract class.
  • Java interface should be implemented using keyword “implements”; A Java abstract class should be extended using keyword “extends”.

All the above arguments talk about the dynamics of implementations of an abstract class and interface(s). Although those are factually correct but lack in answering a fundamental design question, i.e., “When should my software use an abstract class and when should it use an interface”.

To answer this let us begin by asking a few questions, the first one is, Have you ever noticed that when we inherit from interfaces, we use “implements” however when we inherit from an abstract class we use “extends”?, Yes, No? Puzzled?

This little inheritance jargon is the key in understanding the usage of abstract classes vs interfaces. Not only in software engineering but in any engineering field(even in basic english), the keyword “implements” is associated with implementing a functionality and “extends” is associated with extending to enhance the characteristics of a type. Keeping this in mind, Whenever we are implementing we are actually defining “what” a class can do or what it is capable of. For example, a Ball which “is a” Toy is “capable of” bouncing. Got it?, Saw the light?, Not yet?

Maybe Now:

class Ball extends Toy implements Bounceable

So whenever we talk about functionality, think interfaces and whenever we talk about characteristics, think abstract classes(not always, but yes when we analyze in terms of extensions). So, as a general rule of thumb:

Interfaces:

  • Talk about what a class can do.(Functionality)
  • Declare what kind of functionality, a class should implement.
  •  Uses “is capable of” relationship.

Abstract Class(es):

  • Talks about characteristics an object should support.
  • Type of an Object
  • Uses “is a” relationship

Hope this cleared some of the fog.

Collections and Generics

Some Important type of Collections:

1.Sorted Set: Elements of this set are ordered by their natural ordering or by a Comparator.

2. Tree Set: Same as above.

3. Priority Queue: Same as above.

4.List: Has ordering by index.

Tree Set and Prority Queue are non-synchronized.

Nothing specific is said for Sorted set in terms of synchronization in the api.

So what exactly is this over hyped “Natural Ordering”??

Natural ordering is the ordering we achieve by implementing the Comparable interface, i.e., the compareTo() method.

If the compareTo() is overridden in such a way that compareTo() returns a fixed positive integer.Then on retrieving the added elements from that “comparable” collection, they’ll be displayed in the order in which they were added.

Generics:

Q.What is the equivalence of the statement List list??

A.List list is equivalent to List<?> list;

List list is equivalent to List<? extends Object> list.

List list is definitely NOT equivalent to List<Object> list.

Anonymous Inner Classes

The beauty of anonymous inner classes lies in the fact that, that there are so many UNUSUAL/WEIRD ways to define them,

1. Anonymous inner classes, can be defined within a method.(This is similar to method local inner classes)

2.They can also be defined within “AN ARGUMENT TO A METHOD”.

3. Within any class but with no name.

Eg.

class Popcorn

{

public void pop(){System.out.println(“Popcorn”);}

}

class Food

{

Popcorn p=new Popcorn(){

public void pop(){System.out.println();}

};                              <–Please notice the closing semicolon.

}

Now, match this, Food has absolutely no methods of its own(wats pop doing then??),  The popcorn reference variable P will “NOT” refer to an instance of popcorn but to an instance of a subclass of popcorn, which happens to be ANONYMOUS.

Argument local inner classes:

Lets say we have an interface Foo,

interface Foo{

void foof();

}

and i have a class Bar,

class Bar

{

void doStuff(Foo f){}

}

and a class called wonderful which needs to pass a foo implementer object to dostuff of Bar,

This will be done as,

Bar b=new Bar();

b.doStuff(new Foo(){

public void foof(){System.out.println(“foofy”);}

});//This is a classic example of argument local inner classes

Difference between instance creation of static nested class and normal inner class,from outside:

For a static nested class located inside the class BigOuter,

BigOuter.Nest bn=new BigOuter.Nest();

For a normal inner classs

MyOuter.MyInner inner=new MyOuter().new MyInner();

“Poly” means many and “morphos” means forms………blah,blah,blah,blah…………….

Let’s do some coding,

class Stucture

{

         public void design()

        {

                System.out.println(“DVD design”);

          }

class House extends Structure

{

         public void design()

        {

                System.out.println(“house Design”);

          }

          public static void main(String[] args)

           {

                          Structure s=new House();//since house is a structure a valid assignment

                           s.design();          //polymorphism comes into play and a house is designed, nothing very impressive

            }

In the code above a house object is created at runtime and the JVM facillitates the calling of exact overridden design method depending on the type of object as the JVM knows the type of the object being created at runtime. 

Till now , its smooth, we used a superclass reference pointing to its subclass object to demonstrate polymorphism, but what about the case when we pass polymorhic argument method, where 2 overloaded versions of that method exist, one takes a superclass object and other one relies on a subclass object,

class DVD

{

 public void design(DVD dd)

{

System.out.println(“general Dvd”);

}

}

class TestDVD extends DVD

{

public void design(DVD dd)

{

System.out.println(“DVD Design”);

}

public void design(TestDVD dd)

{

System.out.println(“TestDVD Design”);

}

public static void main(String[] args)

{

TestDVD td=new TestDVD();

DVD s=new TestDVD();

td.design(s);

}

}

 

 

No, No, No………captain kirk the output will not be “TestDVD design”, it will be “DVD design”, but why so??……the JVM stilll knows the object being passed is actually a TestDVD so appropriate method should be called, but this is the point where it gets funny, REMEMBER, the choice of which overloaded method to call for which type of argument is not decided at runtime, it is a compile time based choice, the method signature “freezes” at compile time.

Synchronization

Synchronization results in calmness and peace, unsynchronized is chaos.

Imagine a boy(thread 1) and a girl(thread 2) sharing an ice cream jar(synchronized code) on a sunny beach using a single spoon(object).

The synchronization is actually happening due to the single spoon, whose lock is acquired by either of the threads.

The wait() method:

When wait is called inside any thread the execution of that thread is temporarily suspended, by the JVM. Each thread that needs to call wait must declare its motive to do so which it does so by calling wait method using an object on which the thread must wait .To call the wait method this thread must be synchronized with that object, i.e., it must own an exclusive lock of that object. This lock is temporarily released if the thread calls wait().

Polymorphism and generics

This post only holds a few important points one needs to remember  about polymorphism and generics,

1.Polymorphism applies only and only to base types and never for type variables,

E.g

List<String> ls=new ArrayList<String>();

The above statement compiles fine and I was able to use polymorphism for the base types i.e. ArrayList was assigned to List as List was the super type of ArrayList, but the statement below never seems to works,

List<Object> ls=new ArrayList<String>();

Polymorphism is never allowed for type variables. If the type variable is “X” then the reference will only point to the variables of type “X”, and never a super or subtype.