Monday 29 August 2011


Java Interface

In Java, this multiple inheritance problem is solved with a powerful construct called interfaces. Interface can be used to define a generic template and then one or more abstract classes to define partial implementations of the interface. Interfaces just specify the method declaration (implicitly public and abstract) and can only contain fields (which are implicitly public static final). Interface definition begins with a keyword interface. An interface like that of an abstract class cannot be instantiated.
Multiple Inheritance is allowed when extending interfaces i.e. one interface can extend none, one or more interfaces. Java does not support multiple inheritance, but it allows you to extend one class and implement many interfaces.
If a class that implements an interface does not define all the methods of the interface, then it must be declared abstract and the method definitions must be provided by the subclass that extends the abstract class.
Example 1: Below is an example of a Shape interface
interface Shape {
 
      public double area();
      public double volume();
}
Below is a Point class that implements the Shape interface.
public class Point implements Shape {
 
      static int x, y;
      public Point() {
            x = 0;
            y = 0;
      }
      public double area() {
            return 0;
      }
      public double volume() {
            return 0;
      }
      public static void print() {
            System.out.println("point: " + x + "," + y);
      }
      public static void main(String args[]) {
            Point p = new Point();
            p.print();
      }
}
Similarly, other shape objects can be created by interface programming by implementing generic Shape Interface.
Example 2: Below is a java interfaces program showing the power of interface programming in java
Listing below shows 2 interfaces and 4 classes one being an abstract class.
Note: The method toString in class A1 is an overridden version of the method defined in the class named Object. The classes B1 and C1 satisfy the interface contract. But since the class D1 does not define all the methods of the implemented interface I2, the class D1 is declared abstract.
Also,
i1.methodI2() produces a compilation error as the method is not declared in I1 or any of its super interfaces if present. Hence a downcast of interface reference I1 solves the problem as shown in the program. The same problem applies to i1.methodA1(), which is again resolved by a downcast.
When we invoke the toString() method which is a method of an Object, there does not seem to be any problem as every interface or class extends Object and any class can override the default toString() to suit your application needs. ((C1)o1).methodI1() compiles successfully, but produces a ClassCastException at runtime. This is because B1 does not have any relationship with C1 except they are “siblings”. You can’t cast siblings into one another.
When a given interface method is invoked on a given reference, the behavior that results will be appropriate to the class from which that particular object was instantiated. This is runtime polymorphism based on interfaces and overridden methods.
interface I1 {
 
        void methodI1(); // public static by default
}
 
interface I2 extends I1 {
 
        void methodI2(); // public static by default
}
 
class A1 {
 
        public String methodA1() {
               String strA1 = "I am in methodC1 of class A1";
               return strA1;
        }
        public String toString() {
               return "toString() method of class A1";
        }
}
 
class B1 extends A1 implements I2 {
 
        public void methodI1() {
               System.out.println("I am in methodI1 of class B1");
        }
        public void methodI2() {
               System.out.println("I am in methodI2 of class B1");
        }
}
 
class C1 implements I2 {
 
        public void methodI1() {
               System.out.println("I am in methodI1 of class C1");
        }
        public void methodI2() {
               System.out.println("I am in methodI2 of class C1");
        }
}
 
// Note that the class is declared as abstract as it does not
// satisfy the interface contract
abstract class D1 implements I2 {
 
        public void methodI1() {
        }
        // This class does not implement methodI2() hence declared abstract.
}
 
public class InterFaceEx {
 
        public static void main(String[] args) {
               I1 i1 = new B1();
               i1.methodI1(); // OK as methodI1 is present in B1
               // i1.methodI2(); Compilation error as methodI2 not present in I1
               // Casting to convert the type of the reference from type I1 to type I2
               ((I2) i1).methodI2();
               I2 i2 = new B1();
               i2.methodI1(); // OK
               i2.methodI2(); // OK
               // Does not Compile as methodA1() not present in interface reference I1
               // String var = i1.methodA1();
               // Hence I1 requires a cast to invoke methodA1
               String var2 = ((A1) i1).methodA1();
               System.out.println("var2 : " + var2);
               String var3 = ((B1) i1).methodA1();
               System.out.println("var3 : " + var3);
               String var4 = i1.toString();
               System.out.println("var4 : " + var4);
               String var5 = i2.toString();
               System.out.println("var5 : " + var5);
               I1 i3 = new C1();
               String var6 = i3.toString();
               System.out.println("var6 : " + var6); // It prints the Object toString() method
               Object o1 = new B1();
               // o1.methodI1(); does not compile as Object class does not define
               // methodI1()
               // To solve the probelm we need to downcast o1 reference. We can do it
               // in the following 4 ways
               ((I1) o1).methodI1(); // 1
               ((I2) o1).methodI1(); // 2
               ((B1) o1).methodI1(); // 3
               /*
                *
                * B1 does not have any relationship with C1 except they are "siblings".
                *
                * Well, you can't cast siblings into one another.
                *
                */
               // ((C1)o1).methodI1(); Produces a ClassCastException
        }
}
Output
I am in methodI1 of class B1
I am in methodI2 of class B1
I am in methodI1 of class B1
I am in methodI2 of class B1
var2 : I am in methodC1 of class A1
var3 : I am in methodC1 of class A1
var4 : toString() method of class A1
var5 : toString() method of class A1
var6 : C1@190d11
I am in methodI1 of class B1
I am in methodI1 of class B1
I am in methodI1 of class B1
Download Java Interface Program Example
–~~~~~~~~~~~~–

Polymorphism

Polymorphism means one name, many forms. There are 3 distinct forms of Java Polymorphism;
  • Method overloading (Compile time polymorphism)
  • Method overriding through inheritance (Run time polymorphism)
  • Method overriding through the Java interface (Run time polymorphism)
Polymorphism allows a reference to denote objects of different types at different times during execution. A super type reference exhibits polymorphic behavior, since it can denote objects of its subtypes.
interface Shape {
 
        public double area();
        public double volume();
}
 
class Cube implements Shape {
 
        int x = 10;
        public double area( ) {
 
            return (6 * x * x);
        }       
 
        public double volume() {
               return (x * x * x);
        }
 
}
 
class Circle implements Shape {
 
        int radius = 10;
        public double area() {
               return (Math.PI * radius * radius);
        }
        public double volume() {
               return 0;
        }
}
 
public class PolymorphismTest {
 
        public static void main(String args[]) {
               Shape[] s = { new Cube(), new Circle() };
               for (int i = 0; i < s.length; i++) {
                       System.out.println("The area and volume of " + s[i].getClass()
                                      + " is " + s[i].area() + " , " + s[i].volume());
               }
        }
}
Output
The area and volume of class Cube is 600.0 , 1000.0
The area and volume of class Circle is 314.1592653589793 , 0.0
Download Java Polymorphism Program Example
The methods area() and volume() are overridden in the implementing classes. The invocation of the both methods area and volume is determined based on run time polymorphism of the current object as shown in the output.

Interface vs Abstract Class

Interface vs Abstract Class
Taken from http://interview-questions-java.com/abstract-class-interface.htm
1. Abstract class is a class which contain one or more abstract methods, which has to be implemented by sub classes. An abstract class can contain no abstract methods also i.e. abstract class may contain concrete methods. A Java Interface can contain only method declarations and public static final constants and doesn’t contain their implementation. The classes which implement the Interface must provide the method definition for all the methods present.
2. Abstract class definition begins with the keyword “abstract” keyword followed by Class definition. An Interface definition begins with the keyword “interface”.
3. Abstract classes are useful in a situation when some general methods should be implemented and specialization behavior should be implemented by subclasses. Interfaces are useful in a situation when all its properties need to be implemented by subclasses
4. All variables in an Interface are by default - public static final while an abstract class can have instance variables.
5. An interface is also used in situations when a class needs to extend an other class apart from the abstract class. In such situations its not possible to have multiple inheritance of classes. An interface on the other hand can be used when it is required to implement one or more interfaces. Abstract class does not support Multiple Inheritance whereas an Interface supports multiple Inheritance.
6. An Interface can only have public members whereas an abstract class can contain private as well as protected members.
7. A class implementing an interface must implement all of the methods defined in the interface, while a class extending an abstract class need not implement any of the methods defined in the abstract class.
8. The problem with an interface is, if you want to add a new feature (method) in its contract, then you MUST implement those method in all of the classes which implement that interface. However, in the case of an abstract class, the method can be simply implemented in the abstract class and the same can be called by its subclass
9. Interfaces are slow as it requires extra indirection to to find corresponding method in in the actual class. Abstract classes are fast
10.Interfaces are often used to describe the peripheral abilities of a class, and not its central identity, E.g. an Automobile class might
implement the Recyclable interface, which could apply to many otherwise totally unrelated objects.
Note: There is no difference between a fully abstract class (all methods declared as abstract and all fields are public static final) and an interface.
Note: If the various objects are all of-a-kind, and share a common state and behavior, then tend towards a common base class. If all they
share is a set of method signatures, then tend towards an interface.
Similarities:
Neither Abstract classes nor Interface can be instantiated.
Method Overloading:
Method Overriding is achieved when a subclass overrides non-static methods defined in the superclass, following which the new method implementation in the subclass that is executed.
The new method definition must have the same method signature (i.e., method name and parameters) and return type. Only parameter types and return type are chosen as criteria for matching method signature. So if a subclass has its method parameters as final it doesn’t really matter for method overriding scenarios as it still holds true. The new method definition cannot narrow the accessibility of the method, but it can widen it. The new method definition can only specify all or none, or a subset of the exception classes (including their subclasses) specified in the throws clause of the overridden method in the super class
A program to explain the different concepts of Java Method Overridding
class CustomException extends Exception {

}

class SuperClassWithDifferentMethods {

        protected int field1 = 10;
        protected static int field2 = 20;
        public void method1() {
               System.out.println("SuperClassWithDifferentMethods.method1()");
        }
        public final void method2() {
               System.out.println("SuperClassWithDifferentMethods.method2()");
        }
        private void method3() {
               System.out.println("SuperClassWithDifferentMethods.method3()");
        }
        private final void method4() {
<font size=-1>

               System.out.println("SuperClassWithDifferentMethods.method4()");
        }
        public static void method5() {
               System.out.println("SuperClassWithDifferentMethods.method5()");
        }
        public void method6() throws Exception {
               System.out.println("SuperClassWithDifferentMethods.method6()");
        }
        private void method7() {
               System.out.println("SuperClassWithDifferentMethods.method7()");
        }
        private void method8(int x) {
               System.out.println("SuperClassWithDifferentMethods.method8()");
        }
        public static void method9() {
               System.out.println("SuperClassWithDifferentMethods.method9()");
        }
}

class OverridingClass extends SuperClassWithDifferentMethods {

        public int field1 = 30;
        public static int field2 = 40;
        public void method1() {
               System.out.println("OverridingClass.method1()");
        }
        //We can't override a public final method
        /*        public final void method2(){       

         System.out.println("OverridingClass.method2()");

         }*/
        private void method3() {
               System.out.println("OverridingClass.method3()");
        }
        private final void method4() {
               System.out.println("OverridingClass.method4()");
        }
        public static void method5() {
               System.out.println("OverridingClass.method5()");
        }
        public void method6() throws CustomException {
               System.out.println("OverridingClass.method6()");
        }
        public void method7() {
               System.out.println("OverridingClass.method7()");
        }
        public void method8(final int x) {
               System.out.println("OverridingClass.method8()");
        }
        //A static method cannot be overridden to be non-static instance method
        /*public void method9() {

         System.out.println("OverridingClass.method9()");

         }*/
}

public class MethodOverridingDemo {

        public static void main(String[] args) {
               OverridingClass oc1 = new OverridingClass();
               SuperClassWithDifferentMethods sc3 = new OverridingClass();
               oc1.method1();
               oc1.method2();
               //          Since its private, the below 2 methods are not visible
               /*          oc1.method3();

                oc1.method4();*/
               oc1.method5();
               try {
                       oc1.method6();
               } catch (CustomException e) {
                       e.printStackTrace();
               }
               oc1.method7();
               oc1.method8(100);
               System.out.println("oc1.field1 : " + oc1.field1);
               System.out.println("oc1.field2 : " + oc1.field2);
               System.out.println("sc3.field1 : " + sc3.field1);
               System.out.println("sc3.field2 : " + sc3.field2);
               sc3.method5();
               OverridingClass overClass = new OverridingClass();
        SuperClassWithDifferentMethods supClass = (SuperClassWithDifferentMethods) overClass;
               supClass.method5();
               supClass.method1();
        }
}

Output
OverridingClass.method1()
SuperClassWithDifferentMethods.method2()
OverridingClass.method5()
OverridingClass.method6()
OverridingClass.method7()
OverridingClass.method8()
oc1.field1 : 30
oc1.field2 : 40
sc3.field1 : 10
sc3.field2 : 20
SuperClassWithDifferentMethods.method5()
SuperClassWithDifferentMethods.method5()
OverridingClass.method1()
Download MethodOverridingDemo.java
The new method definitions in the subclass OverridingClass have the same signature and the same return type as the methods in the superclass SuperClassWithDifferentMethods. The new overridden method6 definition specifies a subset of the exceptions (CustomException). The new overridden method7 definition also widens the accessibility to public from private. The overriding method8 also declares the parameter to be final, which is not a part of the method signature and Method Overriding holds good. A static method cannot be overridden to be non-static instance method as shown in the overridden method declaration of method9. A static method is class-specific and not part of any object, while overriding methods are invoked on behalf of objects of the subclass. There are no such restrictions on the fields, as for fields only the field names matter. A final method cannot be overridden, an attempt to which will result in a compile-time error. A private method is not accessible outside the class in which it is defined; therefore, a subclass cannot override it.
A subclass must use the ‘super’ keyword in order to invoke an overridden method in the superclass. A subclass cannot override fields of the superclass, but it can hide them. Code in the subclass can use the keyword super to access members, including hidden fields.
The following distinction between invoking instance methods on an object and accessing fields of an object must be noted. When an instance method is invoked on an object using a reference, it is the class of the current object denoted by the reference, not the type of the reference, that determines which method implementation will be executed. When a field of an object is accessed using a reference, it is the type of the reference, not the class of the current object denoted by the reference, that determines which field will actually be accessed. This is demonstrated in the above program
Java toString Method:
Implementing toString method in java is done by overriding the Object’s toString method. The java toString() method is used when we need a string representation of an object. It is defined in Object class. This method can be overridden to customize the String representation of the Object. Below is a program showing the use of the Object’s Default toString java method.
class PointCoordinates {

        private int x, y;
        public PointCoordinates(int x, int y) {
               this.x = x;
               this.y = y;
        }
        public int getX() {
               return x;
        }
        public int getY() {
               return y;
        }
}

public class ToStringDemo {

        public static void main(String args[]) {
               PointCoordinates point = new PointCoordinates(10, 10);
               // using the Default Object.toString() Method
               System.out.println("Object toString() method : " + point);
               // implicitly call toString() on object as part of string concatenation
               String s = point + " testing";
               System.out.println(s);
        }
}

Download
ToStringDemo.java
When you run the ToStringDemo program, the output is:
Object toString() method : PointCoordinates@119c082
<br /><font size=-1>

PointCoordinates@119c082 testing
In the above example when we try printing PointCoordinates object, it internally calls the Object’s toString() method as we have not overridden the java toString() method. Since out example has no toString method, the default one in Object is used. The format of the default toString method of the Object is as shown below.
Class Name, “@”, and the hex version of the object’s hashcode concatenated into a string.
The default hashCode method in Object is typically implemented by converting the memory address of the object into an integer.
Below is an example shown of the same program by Overriding the default Object toString() method. The toString() method must be descriptive and should generally cover all the contents of the object.
class PointCoordinates {

        private int x, y;
        public PointCoordinates(int x, int y) {
               this.x = x;
               this.y = y;
        }
        public int getX() {
               return x;
        }
        public int getY() {
               return y;
        }
        // Custom toString() Method.
        public String toString() {
               return "X=" + x + " " + "Y=" + y;
        }
}

public class ToStringDemo2 {

        public static void main(String args[]) {
               PointCoordinates point = new PointCoordinates(10, 10);
               System.out.println(point);
               String s = point + " testing";
               System.out.println(s);
        }
}
Download ToStringDemo2.java
When you run the ToStringDemo2 program, the output is:
X=10 Y=10
X=10 Y=10 testing
Java String Classes:

Strings in java

Java String Class is immutable, i.e. Strings in java, once created and initialized, cannot be changed on the same reference. A java.lang.String class is final which implies no class and extend it. The java.lang.String class differs from other classes, one difference being that the String objects can be used with the += and + operators for concatenation.
Two useful methods for String objects are equals( ) and substring( ). The equals( ) method is used for testing whether two Strings contain the same value. The substring( ) method is used to obtain a selected portion of a String.

No comments: