Object Oriented Programming (OOPS)Agenda:Data Hiding :
Example: class Account { private double balance; ......................; ......................; } After providing proper username and password only , we can access our Account information. The main advantage of data hiding is security. Abstraction :
By using ATM GUI screen bank people are highlighting the set of services what they are offering without highlighting internal implementation. The main advantages of Abstraction are:
By using interfaces (GUI screens) we can implement abstraction Encapsulation :
Example: ![]() Every data member should be declared as private and for every member we have to maintain getter & Setter methods. The main advantages of encapsulation are :
The main disadvantage of encapsulation is it increases length of the code and slows down execution. Tightly encapsulated class :A class is said to be tightly encapsulated if and only if every variable of that class declared as private whether the variable has getter and setter methods or not , and whether these methods declared as public or not, these checkings are not required to perform. Example: class Account { private double balance; public double getBalance() { return balance; } }Which of the following classes are tightly encapsulated? ![]() Which of the following classes are tightly encapsulated? class A { int x=10; //not } class B extends A { private int y=20; //not } class C extends B { private int z=30; //not }Note: if the parent class is not tightly encapsulated then no child class is tightly encapsulated. IS-A Relationship(inheritance) :
Example: class Parent { public void methodOne(){ } } class Child extends Parent { public void methodTwo() { } } ![]() Conclusion :
The common methods which are required for housing loan, vehicle loan, personal loan and education loan we can define into a separate class in parent class loan. So that automatically these methods are available to every child loan class. Example: class Loan { //common methods which are required for any type of loan. } class HousingLoan extends Loan { //Housing loan specific methods. } class EducationLoan extends Loan { //Education Loan specific methods. }
Diagram: ![]() Multiple inheritance :Having more than one Parent class at the same level is called multiple inheritance. Example:![]() Any class can extends only one class at a time and can't extends more than one class simultaneously hence java won't provide support for multiple inheritance. Example:![]() But an interface can extends any no. Of interfaces at a time hence java provides support for multiple inheritance through interfaces. Example:![]() If our class doesn't extends any other class then only our class is the direct child class of object. Example:![]() If our class extends any other class then our class is not direct child class of object, It is indirect child class of object , which forms multilevel inheritance. Example 1: ![]() Example 2: ![]() Why java won't provide support for multiple inheritance? There may be a chance of raising ambiguity problems. Example:![]() Why ambiguity problem won't be there in interfaces? Interfaces having dummy declarations and they won't have implementations hence no ambiguity problem. Example:![]() Cyclic inheritance :Cyclic inheritance is not allowed in java. Example 1:![]() Example 2: ![]() HAS-A relationship:
Example: class Engine { //engine specific functionality } class Car { Engine e=new Engine(); //........................; //........................; //........................; }
Composition vs Aggregation:Composition:Without existing container object if there is no chance of existing contained objects then the relationship between container object and contained object is called composition which is a strong association. Example:University consists of several departments whenever university object destroys automatically all the department objects will be destroyed that is without existing university object there is no chance of existing dependent object hence these are strongly associated and this relationship is called composition. Example:![]() Aggregation :Without existing container object if there is a chance of existing contained objects such type of relationship is called aggregation. In aggregation objects have weak association. Example:Within a department there may be a chance of several professors will work whenever we are closing department still there may be a chance of existing professor object without existing department object the relationship between department and professor is called aggregation where the objects having weak association. Example:![]() Note : In composition container , contained objects are strongly associated, and but container object holds contained objects directly Method signature:In java, method signature consists of name of the method followed by argument types. Example:![]()
class Test { public void m1(double d) { } public void m2(int i) { } public static void main(String ar[]) { Test t=new Test(); t.m1(10.5); t.m2(10); t.m3(10.5); //CE } } CE : cannot find symbol symbol : method m3(double) location : class TestWithin the same class we can't take 2 methods with the same signature otherwise we will get compile time error. Example: public void methodOne() { } public int methodOne() { return 10; } Output: Compile time error methodOne() is already defined in Test Polymorphism:Same name with different forms is the concept of polymorphism.Example 1: We can use same abs() method for int type, long type, float type etc. Example:
Example 2:
Diagram: ![]() Diagram: 3 Pillars of OOPS ![]() 1) Inheritance talks about reusability. 2) Polymorphism talks about flexibility. 3) Encapsulation talks about security. Beautiful definition of polymorphism:A boy starts love with the word friendship, but girl ends love with the same word friendship, word is the same but with different attitudes. This concept is nothing but polymorphism. Overloading :
Case 1: Automatic promotion in overloading.
The following are various possible automatic promotions in overloading. Diagram : ![]() Example: class Test { public void methodOne(int i) { System.out.println("int-arg method"); } public void methodOne(float f) //overloaded methods { System.out.println("float-arg method"); } public static void main(String[] args) { Test t=new Test(); //t.methodOne('a');//int-arg method //t.methodOne(10l);//float-arg method t.methodOne(10.5);//C.E:cannot find symbol } }Case 2: class Test { public void methodOne(String s) { System.out.println("String version"); } public void methodOne(Object o) //Both methods are said to //be overloaded methods. { System.out.println("Object version"); } public static void main(String[] args) { Test t=new Test(); t.methodOne("arun");//String version t.methodOne(new Object());//Object version t.methodOne(null);//String version } }
Note :
class Test{ public void methodOne(String s){ System.out.println("String version"); } public void methodOne(StringBuffer s){ System.out.println("StringBuffer version"); } public static void main(String[] args) { Test t=new Test(); t.methodOne("arun");//String version t.methodOne(new StringBuffer("sai"));//StringBuffer version t.methodOne(null);//CE : reference to m1() is ambiquous } }Output: ![]() Case 4: class Test { public void methodOne(int i,float f) { System.out.println("int-float method"); } public void methodOne(float f,int i){ System.out.println("float-int method"); } public static void main(String[] args) { Test t=new Test(); t.methodOne(10,10.5f);//int-float method t.methodOne(10.5f,10);//float-int method t.methodOne(10,10); //C.E: //CE:reference to methodOne is ambiguous, //both method methodOne(int,float) in Test //and method methodOne(float,int) in Test match t.methodOne(10.5f,10.5f); //C.E:cannot find symbol symbol : methodOne(float, float) location : class Test } }Case 5 : class Test{ public void methodOne(int i) { System.out.println("general method"); } public void methodOne(int...i) { System.out.println("var-arg method"); } public static void main(String[] args) { Test t=new Test(); t.methodOne();//var-arg method t.methodOne(10,20);//var-arg method t.methodOne(10);//general method } } In general var-arg method will get less priority that is if no other method matched then only var-arg method will get chance for execution it is almost same as default case inside switch. Case 6:class Animal{ } class Monkey extends Animal{} class Test{ public void methodOne(Animal a) { System.out.println("Animal version"); } public void methodOne(Monkey m) { System.out.println("Monkey version"); } public static void main(String[] args) { Test t=new Test(); Animal a=new Animal(); t.methodOne(a);//Animal version Monkey m=new Monkey(); t.methodOne(m);//Monkey version Animal a1=new Monkey(); t.methodOne(a1);//Animal version } } In overloading method resolution is always based on reference type and runtime object won't play any role in overloading. Overriding :
Note: In overriding runtime object will play the role and reference type is dummy. Rules for overriding :
Checked Vs Un-checked Exceptions :
Diagram: ![]() Rule: While overriding if the child class method throws any checked exception compulsory the parent class method should throw the same checked exception or its parent otherwise we will get compile time error. But there are no restrictions for un-checked exceptions. Example: class Parent { public void methodOne() {} } class Child extends Parent{ public void methodOne()throws Exception {} } Output: Compile time error : methodOne() in Child cannot override methodOne() in Parent; overridden method does not throw java.lang.Exception Examples : ![]() ![]() Overriding with respect to static methods:Case 1:We can't override a static method as non static. Example: class Parent { public static void methodOne(){} //here static methodOne() method is a class level } class Child extends Parent { public void methodOne(){} //here methodOne() method is a object level hence // we can't override methodOne() method } output : CE: methodOne in Child can't override methodOne() in Parent ; overriden method is staticCase 2: Similarly we can't override a non static method as static. Case 3:class Parent { public static void methodOne() {} } class Child extends Parent { public static void methodOne() {} } It is valid. It seems to be overriding concept is applicable for static methods but it is not overriding it is method hiding. METHOD HIDING :
All rules of method hiding are exactly same as overriding except the following differences.
Example: class Parent { public static void methodOne() { System.out.println("parent class"); } } class Child extends Parent{ public static void methodOne(){ System.out.println("child class"); } } class Test{ public static void main(String[] args) { Parent p=new Parent(); p.methodOne();//parent class Child c=new Child(); c.methodOne();//child class Parent p1=new Child(); p1.methodOne();//parent class } } Note: If both Parent and Child class methods are non static then it will become overriding and method resolution is based on runtime object. In this case the output is Parent class Child class Child class Overriding with respect to Var-arg methods:A var-arg method should be overridden with var-arg method only. If we are trying to override with normal method then it will become overloading but not overriding. Example: class Parent { public void methodOne(int... i){ System.out.println("parent class"); } } class Child extends Parent { //overloading but not overriding. public void methodOne(int i) { System.out.println("child class"); } } class Test { public static void main(String[] args) { Parent p=new Parent(); p.methodOne(10);//parent class Child c=new Child(); c.methodOne(10);//child class Parent p1=new Child(); p1.methodOne(10);//parent class } } In the above program if we replace child class method with var arg then it will become overriding. In this case the output is Parent class Child class Child class Overriding with respect to variables:
Example: class Parent { int x=888; } class Child extends Parent { int x=999; } class Test { public static void main(String[] args) { Parent p=new Parent(); System.out.println(p.x);//888 Child c=new Child(); System.out.println(c.x);//999 Parent p1=new Child(); System.out.println(p1.x);//888 } } Note: In the above program Parent and Child class variables, whether both are static or non static whether one is static and the other one is non static there is no change in the answer. Differences between overloading and overriding ?
Note:
Consider the method in parent class
What is the difference between ArrayList l=new ArrayList() & List l=new ArrayList() ?
IIQ : In how many ways we can create an object ? (or) In how many ways get an object in java ?
Constructors :
Example: class Student { String name; int rollno; Student(String name,int rollno) //Constructor { this.name=name; this.rollno=rollno; } public static void main(String[] args) { Student s1=new Student("vijayabhaskar",101); Student s2=new Student("bhaskar",102); } } Diagram: ![]() Constructor Vs instance block:
Demo program to track no of objects created for a class: class Test { static int count=0; { count++; //instance block } Test() {} Test(int i) {} public static void main(String[] args) { Test t1=new Test(); Test t2=new Test(10); Test t3=new Test(); System.out.println(count);//3 } } Rules to write constructors:
Example: class Test { static Test() {} } Output: Modifier static not allowed here Default constructor:
Prototype of default constructor:
super() vs this():The 1st line inside every constructor should be either super() or this() if we are not writing anything compiler will always generate super(). Case 1: We have to take super() (or) this() only in the 1st line of constructor. If we are taking anywhere else we will get compile time error. Example: class Test { Test() { System.out.println("constructor"); super(); } } Output: Compile time error. Call to super must be first statement in constructorCase 2: We can use either super() (or) this() but not both simultaneously. Example: class Test { Test() { super(); this(); } } Output: Compile time error. Call to this must be first statement in constructorCase 3: We can use super() (or) this() only inside constructor. If we are using anywhere else we will get compile time error. Example: class Test { public void methodOne() { super(); } } Output: Compile time error. Call to super must be first statement in constructor That is we can call a constructor directly from another constructor only. Diagram:![]() Example:
Example: class Test { public static void main(String[] args) { System.out.println(super.hashCode()); } } Output: Compile time error. Non-static variable super cannot be referenced from a static context. Overloaded constructors :A class can contain more than one constructor and all these constructors having the same name but different arguments and hence these constructors are considered as overloaded constructors. Example: class Test { Test(double d){ System.out.println("double-argument constructor"); } Test(int i) { this(10.5); System.out.println("int-argument constructor"); } Test() { this(10); System.out.println("no-argument constructor"); } public static void main(String[] args) { Test t1=new Test(); //no-argument constructor/int-argument //constructor/double-argument constructor Test t2=new Test(10); //int-argument constructor/double-argument constructor Test t3=new Test(10.5);//double-argument constructor } }
Example: ![]() We can't create object for abstract class but abstract class can contain constructor what is the need ? Abstract class constructor will be executed for every child class object creation to perform initialization of child class object only. Which of the following statement is true ?
Example: abstract class Parent { Parent() { System.out.println(this.hashCode()); //11394033//here this means child class object } } class Child extends Parent { Child() { System.out.println(this.hashCode());//11394033 } } class Test { public static void main(String[] args) { Child c=new Child(); System.out.println(c.hashCode());//11394033 } } Case 1: recursive method call is always runtime exception where as recursive constructor invocation is a compile time error. Note:Recursive functions:A function is called using two methods (types).
Nested call:
Example: public static void methodOne() { methodTwo(); } public static void methodTwo() { methodOne(); } Recursive call:
Example: public void methodOne() { methodOne(); }Example: ![]() Note: Compiler is responsible for the following checkings.
Case 2: ![]()
Case 3: class Parent { Parent()throws java.io.IOException {} } class Child extends Parent {} Output: Compile time error Unreported exception java.io.IOException in default constructor. Example: class Parent { Parent()throws java.io.IOException {} } class Child extends Parent { Child()throws Exception { super(); } } If Parent class constructor throws some checked exception compulsory Child class constructor should throw the same checked exception (or) its Parent. Singleton classes :For any java class if we are allow to create only one object such type of class is said to be singleton class. Example: 1) Runtime class 2) ActionServlet 3) ServiceLocator 4) BusinessDelegate Runtime r1=Runtime.getRuntime(); //getRuntime() method is a factory method Runtime r2=Runtime.getRuntime(); Runtime r3=Runtime.getRuntime(); ................................................. ................................................. System.out.println(r1==r2);//true System.out.println(r1==r3);//true Diagram: ![]() Advantage of Singleton class : Creation of our own singleton classes:We can create our own singleton classes for this we have to use private constructor, static variable and factory method. Example: class Test { private static Test t=null; private Test() {} public static Test getTest() //getTest() method is a factory method { if(t==null) { t=new Test(); } return t; } } class Client { public static void main(String[] args) { System.out.println(Test.getTest().hashCode());//1671711 System.out.println(Test.getTest().hashCode());//1671711 System.out.println(Test.getTest().hashCode());//1671711 System.out.println(Test.getTest().hashCode());//1671711 } } Diagram: ![]() Note: We can create any xxxton classes like(double ton,trible ton...etc) Example: class Test { private static Test t1=null; private static Test t2=null; private Test() {} public static Test getTest() //getTest() method is a factory method { if(t1==null) { t1=new Test(); return t1; } else if(t2==null) { t2=new Test(); return t2; } else { if(Math.random()<0.5) //Math.random() limit : 0<=x<1 return t1; else return t2; } } } class Client { public static void main(String[] args) { System.out.println(Test.getTest().hashCode());//1671711 System.out.println(Test.getTest().hashCode());//11394033 System.out.println(Test.getTest().hashCode());//11394033 System.out.println(Test.getTest().hashCode());//1671711 } } IIQ : We are not allowed to create child class but class is not final , How it is Possible ?By declaring every constructor has private.class Parent { private Parent() { }We can't create child class for this class Note : When ever we are creating child class object automatically parent class constructor will be executed but parent object won't be created. class Parent { Parent() { System.out.println(this.hashCode()); //123 } } class Child extends Parent { Child() { System.out.println(this.hashCode());//123 } } class Test { public static void main(String ar[]) { Child c=new Child(); System.out.println(c.hashCode());//123Which of the following is true ?
Factory method:By using class name if we are calling a method and that method returns the same class object such type of method is called factory method. Example:Runtime r=Runtime.getRuntime();//getRuntime is a factory method. DateFormat df=DateFormat.getInstance(); If object creation required under some constraints then we can implement by using factory method. Static control flow :Example: ![]() Analysis: ![]() Output: E:\scjp>javac Base.java E:\scjp>java Base 0 First static block Second static block 20 Main method Read indirectly write only state (or) RIWO :With in the static block if we are trying to read any variable then that read is considered as "direct read" If a variable is in RIWO state then we can't perform read operation directly otherwise we will get compile time error saying " illegal forward reference ". Example: ![]() Static control flow parent to child relationship :![]() Analysis: ![]() Output: E:\scjp>java Derived 0 Base static block 0 Derived first static block Derived second static block 200 Derived main Output: E:\scjp>java Base 0 Base static block 20 Basic main Whenever we are executing Child class the following sequence of events will be performed automatically.
Note : When ever we are loading child class autimatically the parent class will be loaded but when ever we are loading parent class the child class don't be loaded automatically. Static block:
The native libraries should be loaded at the time of class loading hence we have to define that activity inside static block. Example: class Test { static { System.loadLibrary("native library path"); } } Ex 2 : Every JDBC driver class internally contains a static block to register the driver with DriverManager hence programmer is not responsible to define this explicitly. Example: class Driver { static { //Register this driver with DriverManager } }IIQ : Without using main() method is it possible to print some statements to the console? Ans : Yes, by using static block. Example: class Google { static { System.out.println("hello i can print"); System.exit(0); } } Output: Hello i can printIIQ : Without using main() method and static block is it possible to print some statements to the console ? Example 1: class Test { static int i=methodOne(); public static int methodOne() { System.out.println("hello i can print"); System.exit(0); return 10; } } Output: Hello i can printExample 2: class Test { static Test t=new Test(); Test() { System.out.println("hello i can print"); System.exit(0); } } Output: Hello i can printExample 3: class Test { static Test t=new Test(); { System.out.println("hello i can print"); System.exit(0); } } Output: Hello i can print IIQ : Without using System.out.println() statement is it possible to print some statement to the console ? Example: class Test { public static void main(String[] args) { System.err.println("hello"); } } Note : Without using main() method we can able to print some statement to the sonsole , but this rule is applicable untill 1.6 version from 1.7 version onwards to run java program main() method is mandatory. class Test { static { System.out.println("ststic block"); System.exit(0); } }It is valid in 1.6 version but invalid or won't run in 1.7 version Instance control flow:![]() Analysis: i=0[RIWO] j=0[RIWO] i=10[R&W] j=20[R&W]Output: ![]() Whenever we are executing a java class static control flow will be executed. In the Static control flow Whenever we are creating an object the following sequence of events will be performed automatically.
Note: static control flow is one time activity and it will be executed at the time of class loading. Instance control flow in Parent to Child relationship :Example: class Parent { int x=10; { methodOne(); System.out.println("Parent first instance block"); } Parent() { System.out.println("parent class constructor"); } public static void main(String[] args) { Parent p=new Parent(); System.out.println("parent class main method"); } public void methodOne() { System.out.println(y); } int y=20; } class Child extends Parent { int i=100; { methodTwo(); System.out.println("Child first instance block"); } Child() { System.out.println("Child class constructor"); } public static void main(String[] args) { Child c=new Child(); System.out.println("Child class main method"); } public void methodTwo() { System.out.println(j); } { System.out.println("Child second instance block"); } int j=200; } Output: E:\scjp>javac Child.java E:\scjp>java Child 0 Parent first instance block Parent class constructor 0 Child first instance block Child second instance block Child class constructor Child class main method Whenever we are creating child class object the following sequence of events will be executed automatically.
Note: Object creation is the most costly operation in java and hence if there is no specific requirement never recommended to crate objects. Example 1: public class Initilization { private static String methodOne(String msg) //-->1 { System.out.println(msg); return msg; } public Initilization() //-->4 { m=methodOne("1"); //-->9 } { //-->5 m=methodOne("2"); //-->7 } String m=methodOne("3"); //-->6 , //-->8 public static void main(String[] args) //-->2 { Object obj=new Initilization(); //-->3 } }Analysis: ![]() Output: 2 3 1 Example 2: public class Initilization { private static String methodOne(String msg) //-->1 { System.out.println(msg); return msg; } static String m=methodOne("1"); //-->2, //-->5 { m=methodOne("2"); } static //-->3 { m=methodOne("3"); //-->6 } public static void main(String[] args) //-->4 { Object obj=new Initilization(); } } Output: 1 3 2 We can't access instance variables directly from static area because at the time of execution of static area JVM may not identify those members. Example:![]()
Type casting:Parent class reference can be used to hold Child class object but by using that reference we can't call Child specific methods. Example: Object o=new String("ashok");//valid System.out.println(o.hashCode());//valid System.out.println(o.length());// Similarly we can use interface reference to hold implemented class object. Example:Runnable r=new Thread(); Type casting syntax: ![]() Compile time checking :Rule 1: The type of "d" and "c" must have some relationship [either Child to Parent (or) Parent to Child (or) same type] otherwise we will get compile time error saying inconvertible types. Example 1: ![]() Example 2: ![]() Rule 2: "C" must be either same (or) derived type of "A" otherwise we will get compile time error saying incompatible types. ![]() Example 2: ![]() Runtime checking :The underlying object type of "d" must be either same (or) derived type of "C" otherwise we will get runtime exception saying ClassCastException. Example:![]() Diagram: ![]() Base1 b=new Derived2();//valid Object o=(Base1)b;//valid Object o1=(Base2)o;//invalid Object o2=(Base2)b;//invalid Base2 b1=(Base1)(new Derived1());//invalid Base2 b2=(Base2)(new Derived3());//valid Base2 b2=(Base2)(new Derived1());//invalid Through Type Casting just we are converting the type of object but not object itself that is we are performing type casting but not object casting. Through Type Casting we are not create any new objects for the existing objects we are providing another type of reference variable(mostly Parent type). Example: ![]() Example 1: ![]() Example 2: ![]() It is overriding and method resolution is based on runtime object. C c=new C(); c.methodOne();//c ((B)c).methodOne();//c ((A)((B)c)).methodOne();//c Example 3: ![]() It is method hiding and method resolution is based on reference type. C c=new C(); c.methodOne();//C ((B)c).methodOne();//B ((A)((B)c)).methodOne();//A Example 4: ![]() C c=new C(); System.out.println(c.x);//999 System.out.println(((B)c).x);//888 System.out.println(((A)((B)c)).x);//777
Coupling :The degree of dependency between the components is called coupling.Example: class A { static int i=B.j; } class B extends A { static int j=C.methodOne(); } class C extends B { public static int methodOne() { return D.k; } } class D extends C { static int k=10; public static void main(String[] args) { D d=new D(); } }The above components are said to be tightly coupled to each other because the dependency between the components is more. Tightly coupling is not a good programming practice because it has several serious disadvantages.
It is always recommended to maintain loosely coupling between the components. Cohesion:For every component we have to maintain a clear well defined functionality such type of component is said to be follow high cohesion. Diagram: ![]() High cohesion is always good programming practice because it has several advantages.
Note: It is highly recommended to follow loosely coupling and high cohesion. |
BACK |