Showing posts with label Core Java. Show all posts
Showing posts with label Core Java. Show all posts

Friday, September 12, 2014

Object Oriented Programming Features

  1. Data Hiding
  2. Abstraction
  3. Encapsulation
  4. Has-A relationship
  5. Is-A relationship
  6. Method signature
  7. Overloading
  8. Overriding
  9. Method hiding
  10. Static control flow
  11. Instance control flow
  12. Constructors
  13. Coupling and Cohesion
1. Data Hiding
We are not allowed to provide access to our data directly to the outside person; we can achieve this by declaring data members as private. By this we can achieve security. It is highly recommended to declare data members as private.

2. Abstraction
Hiding implementation details is the concept of abstraction.
Adv:
a. Security: We are not highlighting our implementation
b. Enhancement: Without effecting outside person we are allowed to change our internal logic, hence enhancement is every easy.
c. It improves the maintainability (modularity)

3. Encapsulation
If any class follows data hiding and abstraction such type of class is said to be encapsulated class
i.e. Encapsulation = Data hiding + abstraction
eg:
class Student
{
private String name;
public String getName() // Accessor
{
return name;
}

public void setName(String name) // Mutator
{
this.name = name;
}
}
Here the outside person is not allowed to access our data directly. They can access by using getter and setter methods. Hence we are hiding the data behind the methods. This is the central concept of encapsulation.
Adv of Encapsulation:
     a. Security
     b. Enhancement
     c. Improves maintainability
     d. Modularity improves

Limitation of Encapsulation:
     a. Encapsulation increases the code and slows down the execution.

Tightly encapsulated class
A class is said to be tightly encapsulated if and only all the data members declared as private.
Check which of the following classes are tightly encapsulated.
class Test{
private int x; // tightly encapsulated

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}
}

//It is not tightly encapsulated
class Test{
int x = 10;
}

// A & C are tightly encapsulated
// B is not tightly encapsulated
class A{
private int x = 10;
}
class B extends A{
int y = 30;
}
class C extends B{
private int z = 40;
}

// A, B & C is not tightly encapsulated
// If the parent is not tightly encapsulated then no child class is tightly encapsulated
   class A{
int x = 10;
}
class B extends A{
private int y = 30;
}
class C extends B{
private int z = 40;
}
   

4. IS – A Relationship: Inheritance
     a. IS – A is also known as Inheritance.
     b. By using extends keyword we can implement.
     c. Reusability is the advantage.
Eg:
class Test{
public static void main (String args[]){
Parent p = new Parent();
p.m1(); //output - Parent m1
p.m2(); //output - Parent m2
p.m3(); //Compile Exception

Child c = new Child();
c.m1(); //output - Child m1
c.m2(); //output - Parent m2
c.m3(); //output - Child m3

Parent P = new Child();
p.m1(); //output - Child m1
p.m2(); //output - Parent m2
p.m3(); //Compile Exception
}
}

IMPORTANT
If the parent class reference can be used to hold child class object by using that reference we are allowed to call only parent class specific methods. If these methods are overridden in the child class then the child class methods will execute at runtime.
By using that reference, if we are trying to call child class specific method, we will get compile time error.

Limitation of inheritance:
For every child class object creation, all the parent class objects will be created automatically, sometimes it may creates side effects like performance problems. The industry standard accepted level of inheritance is 8.

5. HAS – A Relationship: (Aggregation or Composition)
     a. HAS – A also known as Aggregation or composition
     b. No specific name keyword (new operator we can use)
     c. Reusability is the advantage
     d. Limitation: The dependency between the components will increase so that maintainability and  enhancement will become more complex.
  // Class car has Engine reference
class Car{
Engine e = new Engine();
}

class Engine{
void m1(){}
void m2(){}
}

6. Method Signature
In java method signature consists of method name and arguments. Return type is not part of method signature.
Eg:
class Test{
public void m1(){}  // m1() is the signature
public void m2(int i){}  //m1(int i) is the signature
}

Compiler uses these signatures to map method calls with the method definitions.
Two methods having the same signature is not allowed in java violation leads to compile time error.
Eg: 
class Test {
public void m1(){}
public int m1() { return 10;}
}
It will throw compileTimeException saying m1() is already defined in Test class

class Test{
public int m1(int i){
return 10;
}
Public void m1(int j) {}
}
It will throw compileTimeException saying m1() is already defined in Test class

7. Overloading
In the case of C language two methods with the same name are not allowed for example if we want to know absolute value, we have to use abs() method for integers, lafb() for long values, fabs() for float values. For every data type creating a new method name results more complexity. But in OOP languages two methods having the same is allowed based on the argument, the corresponding method will execute.
Two methods having the same name, but different arguments is possible in java. Such types of methods are considered as overloaded methods.
In the overloading, the signatures of the methods must be different. We never consider return types access modifiers, throws clause in the overloading.
Eg:
class Test{
public void m1(){
System.out.println(“No Arg”);
}
public void m1(int i){
System.out.println(“Int”);
}
public void m1(double d){
System.out.println(“double”);
}

public static void main (String args[]){
Test t = new Test();
t.m1();
t.m1(10);
t.m1(10l);
}
}
These methods are overloaded methods.

In the case of overloading the method resolution takes care by the compiler based on the reference type. Hence overloading is also considered as static polymorphism or Early Binding or Compile time polymorphism.

Case 1: Automatic promotion is overloading
public void m1(){
System.out.println(“No Arg”);
}
public void m1(int i){
System.out.println(“Int”);
}
public void m1(double d){
System.out.println(“double”);
}

public static void main (String args[]){
Test t = new Test();
t.m1(‘a’);  //int
t.m1(10l); //double
t.m1(10f); //double
}

The char datatype automatically promoted to int data type by the compiler which is nothing but automatic promotion.

The following is the chart of automatic promotion:
byte -> short -> int -> long -> float ->double
               char -> int -> long -> float ->double

Case 2: 
class Test {
public void m1(int i, float f){
System.out.println(“int, float”);
}
public void m1(float f , int i){
System.out.println(“float, int”);
}
public static void main(String args[]){
Test t = new Test();
t.m1(10, 10.5f); // int, float
t.m1(10.5f, 10); // float, int
t.m1(10, 10); // compileTimeException refer to m1 is ambiguous 
 // (Here both methods are matchod)
}

}

Case 3:
class Test{
public void m1(String s){
System.out.println(“String version”);
}
public void m1(Object o){
System.out.println(“Object Version”);
}
public static void main (String args[]){
Test t = new Test();
t.m1(“Yash”); //String version
t.m1(new Object()); //Object version
}
      }

Relation is there Object(Super), String(Child)

Case 4: 
class Test{
public void m1(String s){
System.out.println(“String version”);
}
Public void m1(StringBuffer s){
System.out.println(“String Buffer Version”);
}
Public static void main (String args[]){
Test t = new Test();
t.m1(null); //CompileTimeException – ambiguous
   // reference to m1 is ambiguous, both methods got matched
}
}
Here there is no relation between String and StringBuffer

Case 5:
class Test{
public void m1(int i){
System.out.println(“int method”);
}
public void m1(int... i){
System.out.println(“var-arg method”);
}
public static void main(String args[]){
Test t = new Test();
t.m1(); // output var-args method
t.m1(10,20); //output var-args method
t.m1(10); // output int method
}
}
Var-arg methods will always get least priority i.e. if there is no other method matched then only var-arg method will execute.

Case 6:
class Animal {}
class Monkey extends Animal{}
class Test{
public void m1(Animal a){
System.out.println(“Animal Version”);
}
public void m1(Monkey m){
System.out.println(“Monkey Version”);
}
public static void main (String args[]){
Test t = new Test();

Animal a = new Animal();
t.m1(a); // Animal Version

Monkey m = new Monkey();
t.m(m); // Monkey Version

Animal a1 = new Monkey();
t.m1(a1); //Animal version
}
}

In the case of method overloading method resolution is always takes care by compiler based on the reference type.

8. Overriding:
If the child class is not satisfied with parent class implementation, we are allowed to provide our own implementation in the child class. This concept is called overriding.
Eg:
class parent{
//Overridden method
                void m1(){
System.out.println(“Parent m1”);
}
void m2(){
System.out.println(“Parent m2”);
}
}
class child extends parent{
//Overriding method
                void m1(){
System.out.println(“Child m1”);
}
}

class Test{
public static void main(String args[]){
Parent p = new Child(); 
p.m1(); //Child m1
}
}

In the case of method overriding the method resolution always takes care by JVM based on the run time object. Hence overriding is also known as RunTime Polymorphism or Dynamic Polymorphism or Late Binding (until run time, which method will execute we don’t know)
The overriding method resolution is also known as “Dynamic Method Dispatch”.

Rules of Overriding:
1. Method name and list of arguments must be same i.e. Signature of the method name must be same.
2. In the case of overriding the return types must be same until java 1.4 version, but from java 1.5 version co-varient return types are also allowed i.e. If the parent class method return type is p then the return type of child class method need not be p its child classed are also allowed.
Eg 1:
Parent: Object m1(){}
Child: String m1(){}
1.4 – CompileTimeException
1.5 – Valid because co-variant return type allowed

Eg 2:
Parent: String m1(){}
Child: Objectm1(){}
CompileTimeException

Eg 3:
Parent: long m2(){}
Child: int m2(){}
CompileTimeException because return types not allowed for primitive types

Eg 4:
Parent: Long m1(){}
Child: Integer m1(){}
CompileTimeException
Private methods not visible in the child classes. Hence overriding concept is not applicable for private methods


Interfaces

1.      Introduction
2.      Interface Methods
3.      Interface Variables
4.      Marker / Tag Interfaces
5.      Naming conflix in Interfaces

Introduction
An interface defines “Contract between client and service provider”.
From the client point of view an interface defines the set of service what is expecting
From the service provider point of view an interface defines the set of services what he is providing.

Advantages of Interface:
1.       As we are not highlighting our internal implementation. We can achieve security no one is allowed to see our internal logic or formula.
2.       Without effecting outside persons we are allowed to change our internal implementation. Hence enhancement is very easy.
3.       By Using interfaces two different system can able to communicate.
Declaring an Interface:
                  interface Test{
                        void m1(); //By default public abstract
                  }
The allowed modifiers for the interface are public, <default>, abstract, strictfp i.e. we are not allowed to declare interface as the final, violation leads to compile time error.
                  final interface Test{
                        void m1(); // By default public abstract
                  }
It will throw CE saying illegal combination of modifiers interface and final.

Every method present inside an interface is abstract. Hence an interface is considered as 100% pure abstract class.
                  interface Test{
                        void m1(); // By default public abstract
                        void m2();
                  }
                 
                  abstract class Sample implements Test{                     
                        public void m1(){}
                  }
                 
                  class Child extends Sample{
                        public void m2(){}
                  }
While implementing any interface method, compulsory it should be declared as public other wise compile time error.
If a class implementing any interface for all the interface method it should provide implementation otherwise the class has to declared as abstract.
A class can extend only one class at a time but an interface can extend any number of interfaces.
                  interface x{}
                  interface y{}
                  interface extends x,y{}

A class can implement any number of interfaces simultaneously. The following statements are not valid.
1.       A class can extend an interface.
2.       An interface can extend a class
3.       A class can implement another class
4.       An interface can implement another interface
5.       An interface can implement a class



Interface Methods:
Every interface method by default public and abstract always i.e. all the following methods decalaration inside an interface are equal
1.       void m1();
2.       public void m1();
3.       abstract void m1();
4.       public abstract void m1();  -> all are equal

Q: Which of the following method declarations are valid inside an interface.
1.       void m1() {} -> Wrong
2.       void m1(); -> Correct
3.       private void m1(); -> Wrong
4.       protected void m1(); -> Wrong
5.       synchronized void m1(); -> Wrong

Conclusion: As the interface methods are by default abstract and public, we are not allowed to declare interface methods with private, protected, static, native synchronized, final

Interface Variables
Every interface variable is by default public, static and final i.e. the following variable declaration are same inside an interface
1.       int i=10;
2.       public int i=10;
3.       public static int i=10;
4.       public static final int i=10; -> All are same.

As the interface variables are by default public, static and final we are not allowed to declare interface variables with the following modifiers private, protected, volatile and transient.
Eg:
                      interface Test{
                  int i=10;
            }
           
            class Sample implements Test{
                  public void m1(){
                        i=30;
                  }
            }
CompileTime exception cannot assign a value to the final variable.

As the interface variables are final in the implemented class we are allowed to access, but we cannot override it.

Method Naming conflicts in interface
Case 1: If two interfaces contain a method with same signature and return type then in the implemented class one method implementation is enough
            interface Left{
                  void m1();
            }
           
interface Right{
                  void m1();
            }

            class Test implements Left, Right{
                  void m1(){       
                  }
            } -> No exception, it works fine

Case 2: If two interfaces contain a method with the same name, but different arguments we have to provide implementation for the both the methods and these methods acts as overloaded methods
            interface Left{
                  void m1();
            }

            interface Right{
                  void m1(int i);
            }

            class Test implements Left, Right{
                  public void m1(){      
                  }
                 
                  public int m1(int i){
                        return i
                  }
            }

Case 3: If two interfaces having the same method name and same arguments, but different return type, It is not possible to implement those interface simultaneously.
            interface Left{
                  void m1();
            }

            interface Right{
                  int m1();
            }            

            class Test implements Left, Right{
                  public void m1(){      
                  }
                 
                  public int m1(){
                        return 10;
                  }
            }
It will throw compleTime exception.

Variable Naming conflicts in interfaces:
            interface Left{
                  int i =10;
            }

            interface Left{
                  int i =20;
            }

            class Test implements Left, Right{
                  public static void main (String args[]){
                        //System.out.println(i); -> CompliTimeException reference to i is ambiguous
                        System.out.println(Left.i); -> output is 10
                        System.out.println(Right.i); -> output is 20
                  }
            }

Marker / Tag interface:
 By implementing an interface if we are getting some ability such type of interface are called Marker or Tag interfaces.
Eg: Serializable, Clonable, Comparable, Runnable …. Etc.

These interfaces are made for some ability.
Note: If an interface doesn’t contain any method it is always marker interface. Even though an interface contains some methods if the objects will get some ability by implementing that interfaces are also considered as marker interfaces.

Volatile

Volatile is the keyword which can be applicable only for variables i.e. we can’t use for classes and methods. If the value of a variable is changing frequently such type of variables we have to declare with the keyword Volatile.
            For the Volatile variables JVM will create a separate private copy for every Thread. After completing entire transaction by the thread the final value should be updated in the master copy. So the value of Volatile variable is always stable i.e. At variable level we can achieve synchronization by using Volatile keyword.
            For every Thread maintaining a separate copy is always difficult, hence the performance of the system goes down.
            Volatile means the value keep on changing, but final means the value is not allowed to change hence volatile and final combination is useless.

Serialization

The process of saving and object to a file is called Serialization. Strictly Serialization means the process of converting java supported format object to network supported format object OR Process of converting object into stream of bytes.
            If a variable is declared as transient at the time to serialization JVM ignores the value of that transient variable. Instead of original value JVM saves default value. Hence transient means not to serialize.
Example: while saving Account information permanently to a file, we are not allowed to save password for security reasons, such type of variables we have to declare by transient keyword.

We can serialize only serializable objects violation leads to RuntimeException saying “NotSerializableException”. An Object is said to be seriablizable if and only if the corresponding class implements serializable interface.
           
Import java.io.*;
            public class TransientDemo implements Serializable{

                        int i=10;
                        int j=20;
                       
                        public static void main(String args[]) throws Exception{
                                    TransientDemo t1 = new TransientDemo();
                                    System.out.println(t1.i + "----------" + t1.j);
                                   
                                    //Serialization Process
                                    FileOutputStream fos = new FileOutputStream("abc.txt");
                                    ObjectOutputStream oos = new ObjectOutputStream(fos);
                                    oos.writeObject(t1);
                                   
                                    //De-serialization Process
                                    FileInputStream fis = new FileInputStream("abc.txt");
                                    ObjectInputStream ois = new ObjectInputStream(fis);
                                    ois.readObject();
                                   
                                    TransientDemo t2 = (TransientDemo) ois.readObject();
                                    System.out.println(t2.i + "--------" + t2.j);
                        }
            }
            Output: 10----------20
                         10----------20

Case 1: If we won’t implement serializable interface we get RunTimeException java.io.NonSerializableException.
Case 2: If we won’t place “throws Exception” at method we get compile time exception saying unreported exception must be caught or declared to be throws.
Case 3: We should type cast readObject else we get error Incompatable type error.

Analysis:
Case 1:
            int i = 10;
            int j = 20; output: 10----20
                                       10----20

Case 2:                       
            int i = 10;
            transient int j = 20; output: 10----20
                                                      10----0

Case 3:
            transient static int i=10;
            int j=20; output: 10----20
                                       10----20
Transient is useless in case of static variable.
Static variables never part of object state. Hence they are not participating in serialization process. Declaring a static variable as transient is useless & there is not impact

Case 4:
            transient final int i=10;
            int j=20; output: 10----20
                                       10----20
Declaring a final variable as transient is useless and there is no impact. 

Transient

Transient is a keyword which can be only applicable for variables i.e. we are not allowed to use transient keyword for methods and classes.

Synchronized

  1. Synchronized is the keyword which can be apply for methods and blocks i.e. we can’t apply synchronized keyword for classes and variables.
  2. If a method declared as synchronized at a time only one thread is allowed to execute that method on the given object.
  3. Synchronized is the keyword which is always talks about implementation but abstract never talks about implementation. Hence synchronized and abstract combination is illegal for the methods.
Advantages: we can provide thread safety, we can avoid data inconsistency problems.
Disadvantages: Synchronized keyword increased weighting time of threads and hence performance of system goes down. Hence unless and until there is no specific requirement is not then don’t use synchronized keyword in the coding.

Native: The native is the keyword which can apply only for methods i.e. we can’t apply native keyword for classes and variables. A native method means the method which is implemented in non java like c or c++.  Native methods are also known as foreign methods.

Advantages:
1. As the performance of Java is low for improving the performance we can depend on c or c++. This usage can be happened by native keyword.
2. We can communicate Legacy systems by using native keyword.
class Native {
            static{
                        System.loadLibrary("path.of.native.library"); //1. Load native libraries
            }
            native void m1(); //2. Declaring a native method
}

class Client{
            public static void main (String args[]){
                        Native n = new Native();
                        n.m1(); //3. Invoke a native method
            }
}
3. For the native methods, already implementation is available, we are not providing any implementation. Hence native method declaration should be ends with “;”.
4. Native method means already implementation is available, but abstract method means implementation is not available. Hence abstract and native combination is illegal for the  methods.
5. Native & strictfp combination is illegal for methods, because the old languages may not follow IEEE 754 standard for the floating point arithmetic.
6. We can override a native method
Eg: It is recommended to override hascode() method (which is a native method in object class in our class)
    class Object{
                        native hasCode();
}

class Test{
                //override
}
7. We can overload a native method

native and final combination is legal


Static Modifier

The keyword static can be used for classes, methods and variables. We can’t apply static keyword for the top level classes, but we can apply for inner classes.
For every object a separate copy of instance variables will be created, but in the case of static variables a single global copy will be created at class level and shared by all objects of that class.
Example:
public class StaticTest {
            int i = 10;
            static int j =20;
           
            public static void main (String args[]){
                        StaticTest st1 = new StaticTest();
                        st1.i = 100;
                        st1.j = 200;
                       
                        StaticTest st2 = new StaticTest();
                        st2.i = 1000;
                        st2.j = 2000;
                       
                        System.out.println(st1.i + " -------- " + st1.j);
            }
}
Output: 100 -------- 2000

1. Generally static variable are used for class level constants always associated with final modifier. Static methods are utility methods.

2. Non static variable cannot be reference from static context.
Example:
public class StaticTest {
            int i = 10;
           
            public static void main (String args[]){
                        System.out.println(i);
            }
}
It throws compile time exception saying non static variable i cannot be referenced from a static context.

Consider the following declaration:
1.      Int I = 10;
2.      Static int i = 10;
3.      public void m1() {  System.out.println(i); }
4.      public static void m1() { System.out.println(i); }
Which of the following are not allowed simultaneously in the same class.
a.      1 & 2 (correct) (Instance variables can be accessed from instance area)
b.      1 & 4 (wrong) (CE saying non static variable cannot referenced from static context)
c.       2 & 3 (correct) (Static variables can be accessed from anywhere)
d.      2 & 4 (correct) (Static variables can be accessed from anywhere)

3. Usually static methods are utility methods and we should provide complete implementation. But for abstract methods we are not allowed to provide implementation. Hence abstract and static combination is illegal for the methods.

4. We can overload static methods but we can’t override.